Browse Source

Bump dora v0.3.11 (#948)

tags/v0.3.11
Haixuan Xavier Tao GitHub 9 months ago
parent
commit
fb9c42d630
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
44 changed files with 1881 additions and 563 deletions
  1. +11
    -11
      .github/workflows/node_hub_test.sh
  2. +45
    -43
      Cargo.lock
  3. +21
    -21
      Cargo.toml
  4. +1
    -1
      node-hub/dora-argotranslate/pyproject.toml
  5. +16
    -0
      node-hub/dora-dav1d/Cargo.toml
  6. +30
    -0
      node-hub/dora-dav1d/pyproject.toml
  7. +129
    -0
      node-hub/dora-dav1d/src/lib.rs
  8. +2
    -107
      node-hub/dora-dav1d/src/main.rs
  9. +1
    -1
      node-hub/dora-distil-whisper/pyproject.toml
  10. +1
    -1
      node-hub/dora-echo/pyproject.toml
  11. +1
    -1
      node-hub/dora-internvl/pyproject.toml
  12. +1
    -1
      node-hub/dora-ios-lidar/pyproject.toml
  13. +1
    -1
      node-hub/dora-keyboard/pyproject.toml
  14. +1
    -1
      node-hub/dora-kokoro-tts/pyproject.toml
  15. +1
    -1
      node-hub/dora-microphone/pyproject.toml
  16. +1
    -1
      node-hub/dora-object-to-pose/Cargo.toml
  17. +1
    -1
      node-hub/dora-openai-server/pyproject.toml
  18. +1
    -1
      node-hub/dora-opus/pyproject.toml
  19. +1175
    -0
      node-hub/dora-opus/uv.lock
  20. +1
    -1
      node-hub/dora-outtetts/pyproject.toml
  21. +1
    -1
      node-hub/dora-parler/pyproject.toml
  22. +1
    -1
      node-hub/dora-piper/pyproject.toml
  23. +1
    -1
      node-hub/dora-pyaudio/pyproject.toml
  24. +1
    -1
      node-hub/dora-pyorbbecksdk/pyproject.toml
  25. +1
    -1
      node-hub/dora-pyrealsense/pyproject.toml
  26. +1
    -1
      node-hub/dora-qwen/pyproject.toml
  27. +1
    -1
      node-hub/dora-qwen2-5-vl/pyproject.toml
  28. +1
    -1
      node-hub/dora-qwenvl/pyproject.toml
  29. +17
    -0
      node-hub/dora-rav1e/Cargo.toml
  30. +30
    -0
      node-hub/dora-rav1e/pyproject.toml
  31. +371
    -0
      node-hub/dora-rav1e/src/lib.rs
  32. +2
    -349
      node-hub/dora-rav1e/src/main.rs
  33. +1
    -1
      node-hub/dora-rdt-1b/pyproject.toml
  34. +1
    -1
      node-hub/dora-reachy2/pyproject.toml
  35. +1
    -1
      node-hub/dora-sam2/pyproject.toml
  36. +1
    -1
      node-hub/dora-ugv/pyproject.toml
  37. +1
    -1
      node-hub/dora-vad/pyproject.toml
  38. +1
    -1
      node-hub/dora-yolo/pyproject.toml
  39. +1
    -1
      node-hub/llama-factory-recorder/pyproject.toml
  40. +1
    -1
      node-hub/opencv-plot/pyproject.toml
  41. +1
    -1
      node-hub/opencv-video-capture/pyproject.toml
  42. +1
    -1
      node-hub/pyarrow-assert/pyproject.toml
  43. +1
    -1
      node-hub/pyarrow-sender/pyproject.toml
  44. +1
    -1
      node-hub/terminal-input/pyproject.toml

+ 11
- 11
.github/workflows/node_hub_test.sh View File

@@ -27,7 +27,7 @@ else
cargo test

pip install "maturin[zig]"
maturin build --zig
maturin build --release
# If GITHUB_EVENT_NAME is release or workflow_dispatch, publish the wheel on multiple platforms
if [ "$GITHUB_EVENT_NAME" == "release" ] || [ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]; then
# Free up ubuntu space
@@ -36,7 +36,7 @@ else
sudo rm -rf /usr/share/dotnet/
sudo rm -rf /opt/ghc/

maturin publish --skip-existing --zig
maturin publish --skip-existing
# aarch64-unknown-linux-gnu
rustup target add aarch64-unknown-linux-gnu
maturin publish --target aarch64-unknown-linux-gnu --skip-existing --zig
@@ -53,21 +53,20 @@ else
fi

elif [[ -f "Cargo.toml" && -f "pyproject.toml" && "$(uname)" = "Darwin" ]]; then
# x86_64-apple-darwin
pip install "maturin[zig]"
rustup target add x86_64-apple-darwin
maturin build --target x86_64-apple-darwin --zig --release
# aarch64-apple-darwin
maturin build --release
# If GITHUB_EVENT_NAME is release or workflow_dispatch, publish the wheel
if [ "$GITHUB_EVENT_NAME" == "release" ] || [ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]; then
maturin publish --target x86_64-apple-darwin --skip-existing --zig
maturin publish --skip-existing
fi
# aarch64-apple-darwin
rustup target add aarch64-apple-darwin
maturin build --target aarch64-apple-darwin --zig --release
# x86_64-apple-darwin
rustup target add x86_64-apple-darwin
maturin build --target x86_64-apple-darwin --zig --release
# If GITHUB_EVENT_NAME is release or workflow_dispatch, publish the wheel
if [ "$GITHUB_EVENT_NAME" == "release" ] || [ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]; then
maturin publish --target aarch64-apple-darwin --skip-existing --zig
maturin publish --target x86_64-apple-darwin --skip-existing --zig
fi

else
@@ -96,6 +95,7 @@ else
uv run pytest
fi
if [ "$GITHUB_EVENT_NAME" == "release" ] || [ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]; then
uv build
uv publish --check-url https://pypi.org/simple
fi
fi


+ 45
- 43
Cargo.lock View File

@@ -1481,7 +1481,7 @@ dependencies = [

[[package]]
name = "benchmark-example-node"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -1494,7 +1494,7 @@ dependencies = [

[[package]]
name = "benchmark-example-sink"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -2267,7 +2267,7 @@ dependencies = [

[[package]]
name = "communication-layer-pub-sub"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"flume 0.10.14",
"zenoh 0.7.0-rc",
@@ -2275,7 +2275,7 @@ dependencies = [

[[package]]
name = "communication-layer-request-reply"
version = "0.3.10"
version = "0.3.11"

[[package]]
name = "concurrent-queue"
@@ -3052,7 +3052,7 @@ dependencies = [

[[package]]
name = "dora-arrow-convert"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow 54.2.1",
"chrono",
@@ -3063,7 +3063,7 @@ dependencies = [

[[package]]
name = "dora-cli"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"bat",
"clap 4.5.32",
@@ -3102,7 +3102,7 @@ dependencies = [

[[package]]
name = "dora-coordinator"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"ctrlc",
"dora-core",
@@ -3123,7 +3123,7 @@ dependencies = [

[[package]]
name = "dora-core"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-message",
"eyre",
@@ -3142,7 +3142,7 @@ dependencies = [

[[package]]
name = "dora-daemon"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"aligned-vec",
"async-trait",
@@ -3183,12 +3183,13 @@ dependencies = [
"dora-node-api",
"eyre",
"log",
"pyo3",
"structopt",
]

[[package]]
name = "dora-download"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"eyre",
"reqwest 0.12.15",
@@ -3217,7 +3218,7 @@ dependencies = [

[[package]]
name = "dora-kit-car"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"dotenv",
@@ -3252,7 +3253,7 @@ dependencies = [

[[package]]
name = "dora-metrics"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"eyre",
"opentelemetry 0.28.0",
@@ -3273,7 +3274,7 @@ dependencies = [

[[package]]
name = "dora-node-api"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"aligned-vec",
"arrow 54.2.1",
@@ -3298,7 +3299,7 @@ dependencies = [

[[package]]
name = "dora-node-api-c"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow-array 54.2.1",
"dora-node-api",
@@ -3308,7 +3309,7 @@ dependencies = [

[[package]]
name = "dora-node-api-cxx"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow 54.2.1",
"cxx",
@@ -3326,7 +3327,7 @@ dependencies = [

[[package]]
name = "dora-node-api-python"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow 54.2.1",
"dora-daemon",
@@ -3346,7 +3347,7 @@ dependencies = [

[[package]]
name = "dora-object-to-pose"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -3355,7 +3356,7 @@ dependencies = [

[[package]]
name = "dora-openai-proxy-server"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"chrono",
"dora-node-api",
@@ -3376,7 +3377,7 @@ dependencies = [

[[package]]
name = "dora-operator-api"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-arrow-convert",
"dora-operator-api-macros",
@@ -3385,14 +3386,14 @@ dependencies = [

[[package]]
name = "dora-operator-api-c"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-operator-api-types",
]

[[package]]
name = "dora-operator-api-cxx"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"cxx",
"cxx-build",
@@ -3401,7 +3402,7 @@ dependencies = [

[[package]]
name = "dora-operator-api-macros"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"proc-macro2",
"quote",
@@ -3410,7 +3411,7 @@ dependencies = [

[[package]]
name = "dora-operator-api-python"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"aligned-vec",
"arrow 54.2.1",
@@ -3426,7 +3427,7 @@ dependencies = [

[[package]]
name = "dora-operator-api-types"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow 54.2.1",
"dora-arrow-convert",
@@ -3435,18 +3436,19 @@ dependencies = [

[[package]]
name = "dora-rav1e"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"bytemuck",
"dora-node-api",
"eyre",
"log",
"pyo3",
"rav1e",
]

[[package]]
name = "dora-record"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"chrono",
"dora-node-api",
@@ -3458,7 +3460,7 @@ dependencies = [

[[package]]
name = "dora-rerun"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"bytemuck",
"chrono",
@@ -3473,7 +3475,7 @@ dependencies = [

[[package]]
name = "dora-ros2-bridge"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"array-init",
"dora-daemon",
@@ -3496,7 +3498,7 @@ dependencies = [

[[package]]
name = "dora-ros2-bridge-msg-gen"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"anyhow",
"glob",
@@ -3512,7 +3514,7 @@ dependencies = [

[[package]]
name = "dora-ros2-bridge-python"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"arrow 54.2.1",
"dora-ros2-bridge",
@@ -3526,7 +3528,7 @@ dependencies = [

[[package]]
name = "dora-runtime"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"aligned-vec",
"arrow 54.2.1",
@@ -3554,7 +3556,7 @@ dependencies = [

[[package]]
name = "dora-tracing"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"eyre",
"opentelemetry 0.18.0",
@@ -7038,7 +7040,7 @@ dependencies = [

[[package]]
name = "multiple-daemons-example-node"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -7049,14 +7051,14 @@ dependencies = [

[[package]]
name = "multiple-daemons-example-operator"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-operator-api",
]

[[package]]
name = "multiple-daemons-example-sink"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -11004,7 +11006,7 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430"

[[package]]
name = "receive_data"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"chrono",
"dora-node-api",
@@ -11473,7 +11475,7 @@ dependencies = [

[[package]]
name = "rust-dataflow-example-node"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -11484,7 +11486,7 @@ dependencies = [

[[package]]
name = "rust-dataflow-example-sink"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -11492,7 +11494,7 @@ dependencies = [

[[package]]
name = "rust-dataflow-example-sink-dynamic"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -11500,7 +11502,7 @@ dependencies = [

[[package]]
name = "rust-dataflow-example-status-node"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",
@@ -11519,7 +11521,7 @@ dependencies = [

[[package]]
name = "rust-ros2-dataflow-example-node"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"dora-ros2-bridge",
@@ -12343,7 +12345,7 @@ dependencies = [

[[package]]
name = "shared-memory-server"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"bincode",
"eyre",
@@ -13186,7 +13188,7 @@ dependencies = [

[[package]]
name = "terminal-print"
version = "0.3.10"
version = "0.3.11"
dependencies = [
"dora-node-api",
"eyre",


+ 21
- 21
Cargo.toml View File

@@ -49,33 +49,33 @@ members = [
[workspace.package]
edition = "2021"
# Make sure to also bump `apis/node/python/__init__.py` version.
version = "0.3.10"
version = "0.3.11"
description = "`dora` goal is to be a low latency, composable, and distributed data flow."
documentation = "https://dora.carsmos.ai"
license = "Apache-2.0"
repository = "https://github.com/dora-rs/dora/"

[workspace.dependencies]
dora-node-api = { version = "0.3.10", path = "apis/rust/node", default-features = false }
dora-node-api-python = { version = "0.3.10", path = "apis/python/node", default-features = false }
dora-operator-api = { version = "0.3.10", path = "apis/rust/operator", default-features = false }
dora-operator-api-macros = { version = "0.3.10", path = "apis/rust/operator/macros" }
dora-operator-api-types = { version = "0.3.10", path = "apis/rust/operator/types" }
dora-operator-api-python = { version = "0.3.10", path = "apis/python/operator" }
dora-operator-api-c = { version = "0.3.10", path = "apis/c/operator" }
dora-node-api-c = { version = "0.3.10", path = "apis/c/node" }
dora-core = { version = "0.3.10", path = "libraries/core" }
dora-arrow-convert = { version = "0.3.10", path = "libraries/arrow-convert" }
dora-tracing = { version = "0.3.10", path = "libraries/extensions/telemetry/tracing" }
dora-metrics = { version = "0.3.10", path = "libraries/extensions/telemetry/metrics" }
dora-download = { version = "0.3.10", path = "libraries/extensions/download" }
shared-memory-server = { version = "0.3.10", path = "libraries/shared-memory-server" }
communication-layer-request-reply = { version = "0.3.10", path = "libraries/communication-layer/request-reply" }
dora-runtime = { version = "0.3.10", path = "binaries/runtime" }
dora-daemon = { version = "0.3.10", path = "binaries/daemon" }
dora-coordinator = { version = "0.3.10", path = "binaries/coordinator" }
dora-ros2-bridge = { version = "0.3.10", path = "libraries/extensions/ros2-bridge" }
dora-ros2-bridge-msg-gen = { version = "0.3.10", path = "libraries/extensions/ros2-bridge/msg-gen" }
dora-node-api = { version = "0.3.11", path = "apis/rust/node", default-features = false }
dora-node-api-python = { version = "0.3.11", path = "apis/python/node", default-features = false }
dora-operator-api = { version = "0.3.11", path = "apis/rust/operator", default-features = false }
dora-operator-api-macros = { version = "0.3.11", path = "apis/rust/operator/macros" }
dora-operator-api-types = { version = "0.3.11", path = "apis/rust/operator/types" }
dora-operator-api-python = { version = "0.3.11", path = "apis/python/operator" }
dora-operator-api-c = { version = "0.3.11", path = "apis/c/operator" }
dora-node-api-c = { version = "0.3.11", path = "apis/c/node" }
dora-core = { version = "0.3.11", path = "libraries/core" }
dora-arrow-convert = { version = "0.3.11", path = "libraries/arrow-convert" }
dora-tracing = { version = "0.3.11", path = "libraries/extensions/telemetry/tracing" }
dora-metrics = { version = "0.3.11", path = "libraries/extensions/telemetry/metrics" }
dora-download = { version = "0.3.11", path = "libraries/extensions/download" }
shared-memory-server = { version = "0.3.11", path = "libraries/shared-memory-server" }
communication-layer-request-reply = { version = "0.3.11", path = "libraries/communication-layer/request-reply" }
dora-runtime = { version = "0.3.11", path = "binaries/runtime" }
dora-daemon = { version = "0.3.11", path = "binaries/daemon" }
dora-coordinator = { version = "0.3.11", path = "binaries/coordinator" }
dora-ros2-bridge = { version = "0.3.11", path = "libraries/extensions/ros2-bridge" }
dora-ros2-bridge-msg-gen = { version = "0.3.11", path = "libraries/extensions/ros2-bridge/msg-gen" }
dora-ros2-bridge-python = { path = "libraries/extensions/ros2-bridge/python" }
# versioned independently from the other dora crates
dora-message = { version = "0.4.4", path = "libraries/message" }


+ 1
- 1
node-hub/dora-argotranslate/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-argotranslate"
version = "0.3.10"
version = "0.3.11"
description = "Dora Node for Text translating using Argostranslate"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },


+ 16
- 0
node-hub/dora-dav1d/Cargo.toml View File

@@ -4,6 +4,10 @@ edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = []
python = ["pyo3"]

[dependencies]
dav1d = "0.10"
bitstream-io = "2.0"
@@ -12,3 +16,15 @@ structopt = "0.3"
dora-node-api = { workspace = true, features = ["tracing"] }
eyre = "0.6.8"
bytemuck = "1.7.0"
pyo3 = { workspace = true, features = [
"extension-module",
"abi3",
"eyre",
"generate-import-lib",
], optional = true }


[lib]
name = "dora_dav1d"
path = "src/lib.rs"
crate-type = ["lib", "cdylib"]

+ 30
- 0
node-hub/dora-dav1d/pyproject.toml View File

@@ -0,0 +1,30 @@
[build-system]
requires = ["maturin>=0.13.2"]
build-backend = "maturin"

[project]
name = "dora-dav1d"
dynamic = ["version"]
license = { text = "MIT" }
requires-python = ">=3.8"

dependencies = [
"maturin>=1.8.2",
]

scripts = { "dora-dav1d" = "dora_dav1d:py_main" }

[tool.maturin]
features = ["python", "pyo3/extension-module"]

[tool.ruff.lint]
extend-select = [
"D", # pydocstyle
"UP", # Ruff's UP rule
"PERF", # Ruff's PERF rule
"RET", # Ruff's RET rule
"RSE", # Ruff's RSE rule
"NPY", # Ruff's NPY rule
"N", # Ruff's N rule
"I", # Ruff's I rule
]

+ 129
- 0
node-hub/dora-dav1d/src/lib.rs View File

@@ -0,0 +1,129 @@
use dav1d::Settings;
use dora_node_api::{arrow::array::UInt8Array, DoraNode, Event, IntoArrow};
use eyre::{Context, Result};
use log::warn;

fn yuv420_to_bgr(
y_plane: &[u8],
u_plane: &[u8],
v_plane: &[u8],
width: u32,
height: u32,
) -> Vec<u8> {
let width = width as usize;
let height = height as usize;
let mut rgb_data = vec![0u8; width * height * 3]; // Output RGB data buffer

for j in 0..height {
for i in 0..width {
let y_idx = j * width + i; // Index in Y plane
let uv_idx = (j / 2) * (width / 2) + (i / 2); // Index in U/V planes

let y = y_plane[y_idx] as f32;
let u = u_plane[uv_idx] as f32 - 128.0;
let v = v_plane[uv_idx] as f32 - 128.0;

// Convert YUV to RGB using BT.601 standard formula
let r = (y + 1.402 * v).clamp(0.0, 255.0) as u8;
let g = (y - 0.344136 * u - 0.714136 * v).clamp(0.0, 255.0) as u8;
let b = (y + 1.772 * u).clamp(0.0, 255.0) as u8;

// Set the RGB values in the output buffer
let rgb_idx = y_idx * 3;
rgb_data[rgb_idx] = b;
rgb_data[rgb_idx + 1] = g;
rgb_data[rgb_idx + 2] = r;
}
}

rgb_data
}

pub fn lib_main() -> Result<()> {
let mut settings = Settings::new();
// settings.set_n_threads(16);
settings.set_max_frame_delay(1);
let mut dec =
dav1d::Decoder::with_settings(&settings).expect("failed to create decoder instance");

let (mut node, mut events) =
DoraNode::init_from_env().context("Could not initialize dora node")?;

loop {
match events.recv() {
Some(Event::Input {
id,
data,
mut metadata,
}) => {
if let Some(data) = data.as_any().downcast_ref::<UInt8Array>() {
let data = data.values().clone();
match dec.send_data(data, None, None, None) {
Err(e) => {
warn!("Error sending data to the decoder: {}", e);
}
Ok(()) => {
if let Ok(p) = dec.get_picture() {
match p.pixel_layout() {
dav1d::PixelLayout::I420 => {
let y = p.plane(dav1d::PlanarImageComponent::Y);
let u = p.plane(dav1d::PlanarImageComponent::U);
let v = p.plane(dav1d::PlanarImageComponent::V);
let y = yuv420_to_bgr(&y, &u, &v, p.width(), p.height());
let arrow = y.into_arrow();
metadata.parameters.insert(
"encoding".to_string(),
dora_node_api::Parameter::String("bgr8".to_string()),
);
node.send_output(id, metadata.parameters, arrow).unwrap();
}
dav1d::PixelLayout::I400 => {
let y = p.plane(dav1d::PlanarImageComponent::Y);
let vec16: Vec<u16> = bytemuck::cast_slice(&y).to_vec();
let arrow = vec16.into_arrow();
metadata.parameters.insert(
"encoding".to_string(),
dora_node_api::Parameter::String("mono16".to_string()),
);
node.send_output(id, metadata.parameters, arrow).unwrap();
}
_ => {
warn!("Unsupported pixel layout");
continue;
}
};
}
}
}
} else {
warn!("Unsupported data type {}", data.data_type());
continue;
}
}
None => break,
Some(_) => break,
}
}
Ok(())
}

#[cfg(feature = "python")]
use pyo3::{
pyfunction, pymodule,
types::{PyModule, PyModuleMethods},
wrap_pyfunction, Bound, PyResult, Python,
};

#[cfg(feature = "python")]
#[pyfunction]
fn py_main(_py: Python) -> eyre::Result<()> {
lib_main()
}

#[cfg(feature = "python")]
#[pymodule]
fn dora_kit_car(_py: Python, m: Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(py_main, &m)?)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}

+ 2
- 107
node-hub/dora-dav1d/src/main.rs View File

@@ -1,108 +1,3 @@
use dav1d::Settings;
use dora_node_api::{arrow::array::UInt8Array, DoraNode, Event, IntoArrow};
use eyre::{Context, Result};
use log::warn;

fn yuv420_to_bgr(
y_plane: &[u8],
u_plane: &[u8],
v_plane: &[u8],
width: u32,
height: u32,
) -> Vec<u8> {
let width = width as usize;
let height = height as usize;
let mut rgb_data = vec![0u8; width * height * 3]; // Output RGB data buffer

for j in 0..height {
for i in 0..width {
let y_idx = j * width + i; // Index in Y plane
let uv_idx = (j / 2) * (width / 2) + (i / 2); // Index in U/V planes

let y = y_plane[y_idx] as f32;
let u = u_plane[uv_idx] as f32 - 128.0;
let v = v_plane[uv_idx] as f32 - 128.0;

// Convert YUV to RGB using BT.601 standard formula
let r = (y + 1.402 * v).clamp(0.0, 255.0) as u8;
let g = (y - 0.344136 * u - 0.714136 * v).clamp(0.0, 255.0) as u8;
let b = (y + 1.772 * u).clamp(0.0, 255.0) as u8;

// Set the RGB values in the output buffer
let rgb_idx = y_idx * 3;
rgb_data[rgb_idx] = b;
rgb_data[rgb_idx + 1] = g;
rgb_data[rgb_idx + 2] = r;
}
}

rgb_data
}

fn main() -> Result<()> {
let mut settings = Settings::new();
// settings.set_n_threads(16);
settings.set_max_frame_delay(1);
let mut dec =
dav1d::Decoder::with_settings(&settings).expect("failed to create decoder instance");

let (mut node, mut events) =
DoraNode::init_from_env().context("Could not initialize dora node")?;

loop {
match events.recv() {
Some(Event::Input {
id,
data,
mut metadata,
}) => {
if let Some(data) = data.as_any().downcast_ref::<UInt8Array>() {
let data = data.values().clone();
match dec.send_data(data, None, None, None) {
Err(e) => {
warn!("Error sending data to the decoder: {}", e);
}
Ok(()) => {
if let Ok(p) = dec.get_picture() {
match p.pixel_layout() {
dav1d::PixelLayout::I420 => {
let y = p.plane(dav1d::PlanarImageComponent::Y);
let u = p.plane(dav1d::PlanarImageComponent::U);
let v = p.plane(dav1d::PlanarImageComponent::V);
let y = yuv420_to_bgr(&y, &u, &v, p.width(), p.height());
let arrow = y.into_arrow();
metadata.parameters.insert(
"encoding".to_string(),
dora_node_api::Parameter::String("bgr8".to_string()),
);
node.send_output(id, metadata.parameters, arrow).unwrap();
}
dav1d::PixelLayout::I400 => {
let y = p.plane(dav1d::PlanarImageComponent::Y);
let vec16: Vec<u16> = bytemuck::cast_slice(&y).to_vec();
let arrow = vec16.into_arrow();
metadata.parameters.insert(
"encoding".to_string(),
dora_node_api::Parameter::String("mono16".to_string()),
);
node.send_output(id, metadata.parameters, arrow).unwrap();
}
_ => {
warn!("Unsupported pixel layout");
continue;
}
};
}
}
}
} else {
warn!("Unsupported data type {}", data.data_type());
continue;
}
}
None => break,
Some(_) => break,
}
}
Ok(())
fn main() -> eyre::Result<()> {
dora_dav1d::lib_main()
}

+ 1
- 1
node-hub/dora-distil-whisper/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-distil-whisper"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-echo/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-echo"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-internvl/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-internvl"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-ios-lidar/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-ios-lidar"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Your Name", email = "email@email.com" }]
description = "dora-ios-lidar"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-keyboard/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-keyboard"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-kokoro-tts/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-kokoro-tts"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Your Name", email = "email@email.com" }]
description = "dora-kokoro-tts"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-microphone/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-microphone"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-object-to-pose/Cargo.toml View File

@@ -1,6 +1,6 @@
[package]
name = "dora-object-to-pose"
version = "0.3.10"
version = "0.3.11"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html


+ 1
- 1
node-hub/dora-openai-server/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-openai-server"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-opus/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-opus"
version = "0.3.10"
version = "0.3.11"
description = "Dora Node for Text translating using Opus"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },


+ 1175
- 0
node-hub/dora-opus/uv.lock
File diff suppressed because it is too large
View File


+ 1
- 1
node-hub/dora-outtetts/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-outtetts"
version = "0.3.10"
version = "0.3.11"
authors = []
description = "dora-outtetts"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-parler/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-parler"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-piper/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-piper"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
description = "Dora Node for using Agilex piper"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-pyaudio/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-pyaudio"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
license = { text = "MIT" }
readme = "README.md"


+ 1
- 1
node-hub/dora-pyorbbecksdk/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-pyorbbecksdk"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Xiang Yang", email = "Ryu-Yang@qq.com" },


+ 1
- 1
node-hub/dora-pyrealsense/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-pyrealsense"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
description = "Dora Node for capturing video with Pyrealsense"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-qwen/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-qwen"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Your Name", email = "email@email.com" }]
description = "dora-qwen"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-qwen2-5-vl/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-qwen2-5-vl"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/dora-qwenvl/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-qwenvl"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 17
- 0
node-hub/dora-rav1e/Cargo.toml View File

@@ -9,9 +9,26 @@ repository.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = []
python = ["pyo3"]

[dependencies]
rav1e = { version = "0.7.1", features = ["serialize"] }
dora-node-api = { workspace = true, features = ["tracing"] }
eyre = "0.6.8"
log = "0.4"
bytemuck = "1.20"
pyo3 = { workspace = true, features = [
"extension-module",
"abi3",
"eyre",
"generate-import-lib",
], optional = true }


[lib]
name = "dora_rav1e"
path = "src/lib.rs"
crate-type = ["lib", "cdylib"]


+ 30
- 0
node-hub/dora-rav1e/pyproject.toml View File

@@ -0,0 +1,30 @@
[build-system]
requires = ["maturin>=0.13.2"]
build-backend = "maturin"

[project]
name = "dora-rav1e"
dynamic = ["version"]
license = { text = "MIT" }
requires-python = ">=3.8"

dependencies = [
"maturin>=1.8.2",
]

scripts = { "dora-rav1e" = "dora_rav1e:py_main" }

[tool.maturin]
features = ["python", "pyo3/extension-module"]

[tool.ruff.lint]
extend-select = [
"D", # pydocstyle
"UP", # Ruff's UP rule
"PERF", # Ruff's PERF rule
"RET", # Ruff's RET rule
"RSE", # Ruff's RSE rule
"NPY", # Ruff's NPY rule
"N", # Ruff's N rule
"I", # Ruff's I rule
]

+ 371
- 0
node-hub/dora-rav1e/src/lib.rs View File

@@ -0,0 +1,371 @@
// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use std::env::var;

use dora_node_api::arrow::array::{UInt16Array, UInt8Array};
use dora_node_api::{DoraNode, Event, IntoArrow, Parameter};
use eyre::{Context as EyreContext, Result};
use log::warn;
// Encode the same tiny blank frame 30 times
use rav1e::config::SpeedSettings;

use rav1e::*;

fn bgr8_to_yuv420(bgr_data: Vec<u8>, width: usize, height: usize) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
let mut y_plane = vec![0; width * height];
let mut u_plane = vec![0; (width / 2) * (height / 2)];
let mut v_plane = vec![0; (width / 2) * (height / 2)];

for y in 0..height {
for x in 0..width {
let bgr_index = (y * width + x) * 3;
let b = bgr_data[bgr_index] as f32;
let g = bgr_data[bgr_index + 1] as f32;
let r = bgr_data[bgr_index + 2] as f32;

// Corrected YUV conversion formulas
let y_value = (0.299 * r + 0.587 * g + 0.114 * b).clamp(0.0, 255.0);
let u_value = (-0.14713 * r - 0.28886 * g + 0.436 * b + 128.0).clamp(0.0, 255.0);
let v_value = (0.615 * r - 0.51499 * g - 0.10001 * b + 128.0).clamp(0.0, 255.0);

let y_index = y * width + x;
y_plane[y_index] = y_value.round() as u8;

if x % 2 == 0 && y % 2 == 0 {
let uv_index = (y / 2) * (width / 2) + (x / 2);
u_plane[uv_index] = u_value.round() as u8;
v_plane[uv_index] = v_value.round() as u8;
}
}
}

(y_plane, u_plane, v_plane)
}

fn get_yuv_planes(buffer: &[u8], width: usize, height: usize) -> (&[u8], &[u8], &[u8]) {
// Calculate sizes of Y, U, and V planes for YUV420 format
let y_size = width * height; // Y has full resolution
let uv_width = width / 2; // U and V are subsampled by 2 in both dimensions
let uv_height = height / 2; // U and V are subsampled by 2 in both dimensions
let uv_size = uv_width * uv_height; // Size for U and V planes

// Ensure the buffer has the correct size
// if buffer.len() != y_size + 2 * uv_size {
// panic!("Invalid buffer size for the given width and height!");
// }

// Extract Y, U, and V planes
let y_plane = &buffer[0..y_size]; //.to_vec();
let u_plane = &buffer[y_size..y_size + uv_size]; //.to_vec();
let v_plane = &buffer[y_size + uv_size..]; //.to_vec();

(y_plane, u_plane, v_plane)
}

pub fn lib_main() -> Result<()> {
let mut height = std::env::var("IMAGE_HEIGHT")
.unwrap_or_else(|_| "480".to_string())
.parse()
.unwrap();
let mut width = std::env::var("IMAGE_WIDTH")
.unwrap_or_else(|_| "640".to_string())
.parse()
.unwrap();
let speed = var("RAV1E_SPEED").map(|s| s.parse().unwrap()).unwrap_or(10);
let mut enc = EncoderConfig {
width,
height,
speed_settings: SpeedSettings::from_preset(speed),
low_latency: true,
..Default::default()
};
let cfg = Config::new().with_encoder_config(enc.clone());
cfg.validate()?;

let (mut node, mut events) =
DoraNode::init_from_env().context("Could not initialize dora node")?;

loop {
match events.recv() {
Some(Event::Input {
id,
data,
mut metadata,
}) => {
if let Some(Parameter::Integer(h)) = metadata.parameters.get("height") {
height = *h as usize;
};
if let Some(Parameter::Integer(w)) = metadata.parameters.get("width") {
width = *w as usize;
};
let encoding = if let Some(Parameter::String(encoding)) =
metadata.parameters.get("encoding")
{
encoding
} else {
"bgr8"
};
enc = EncoderConfig {
width,
height,
speed_settings: SpeedSettings::from_preset(speed),
low_latency: true,
..Default::default()
};
match encoding {
"mono16" => {
enc.bit_depth = 12;
enc.chroma_sampling = color::ChromaSampling::Cs400;
}
_ => {}
}

let cfg = Config::new().with_encoder_config(enc.clone());
if encoding == "bgr8" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer: Vec<u8> = buffer.values().to_vec();
let (y, u, v) = bgr8_to_yuv420(buffer, width, height);

// Transpose values from BGR to RGB
// let buffer: Vec<u8> = buffer.chunks(3).flat_map(|x| [x[2], x[1], x[0]]).collect();

let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
continue;
}
_ => {
warn!("Unable to send frame ");
continue;
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "yuv420" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer = buffer.values(); //.to_vec();

let (y, u, v) = get_yuv_planes(buffer, width, height);
let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
}
_ => {
warn!("Unable to send frame ");
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "mono16" {
let buffer: &UInt16Array = data.as_any().downcast_ref().unwrap();
let buffer: &[u16] = buffer.values();
// let buffer = shift_u16_slice_to_upper_12_bits(buffer);
let bytes: &[u8] = &bytemuck::cast_slice(&buffer);

let mut ctx: Context<u16> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
// Multiply by 2 the stride as it is going to be width * 2 as we're converting 16-bit to 2*8-bit.
f.planes[0].copy_from_raw_u8(bytes, stride * 2, 2);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
}
_ => {
warn!("Unable to send frame ");
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "rgb8" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer: Vec<u8> = buffer.values().to_vec();
let buffer: Vec<u8> =
buffer.chunks(3).flat_map(|x| [x[2], x[1], x[0]]).collect();
let (y, u, v) = bgr8_to_yuv420(buffer, width, height);

// Transpose values from BGR to RGB

let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
continue;
}
_ => {
warn!("Unable to send frame ");
continue;
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else {
unimplemented!("We haven't worked on additional encodings.");
}
}
Some(Event::Error(_e)) => {
continue;
}
_ => break,
};
}

Ok(())
}

#[cfg(feature = "python")]
use pyo3::{
pyfunction, pymodule,
types::{PyModule, PyModuleMethods},
wrap_pyfunction, Bound, PyResult, Python,
};

#[cfg(feature = "python")]
#[pyfunction]
fn py_main(_py: Python) -> eyre::Result<()> {
lib_main()
}

#[cfg(feature = "python")]
#[pymodule]
fn dora_kit_car(_py: Python, m: Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(py_main, &m)?)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}

+ 2
- 349
node-hub/dora-rav1e/src/main.rs View File

@@ -1,350 +1,3 @@
// Copyright (c) 2019-2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use std::env::var;

use dora_node_api::arrow::array::{UInt16Array, UInt8Array};
use dora_node_api::{DoraNode, Event, IntoArrow, Parameter};
use eyre::{Context as EyreContext, Result};
use log::warn;
// Encode the same tiny blank frame 30 times
use rav1e::config::SpeedSettings;

use rav1e::*;

fn bgr8_to_yuv420(bgr_data: Vec<u8>, width: usize, height: usize) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
let mut y_plane = vec![0; width * height];
let mut u_plane = vec![0; (width / 2) * (height / 2)];
let mut v_plane = vec![0; (width / 2) * (height / 2)];

for y in 0..height {
for x in 0..width {
let bgr_index = (y * width + x) * 3;
let b = bgr_data[bgr_index] as f32;
let g = bgr_data[bgr_index + 1] as f32;
let r = bgr_data[bgr_index + 2] as f32;

// Corrected YUV conversion formulas
let y_value = (0.299 * r + 0.587 * g + 0.114 * b).clamp(0.0, 255.0);
let u_value = (-0.14713 * r - 0.28886 * g + 0.436 * b + 128.0).clamp(0.0, 255.0);
let v_value = (0.615 * r - 0.51499 * g - 0.10001 * b + 128.0).clamp(0.0, 255.0);

let y_index = y * width + x;
y_plane[y_index] = y_value.round() as u8;

if x % 2 == 0 && y % 2 == 0 {
let uv_index = (y / 2) * (width / 2) + (x / 2);
u_plane[uv_index] = u_value.round() as u8;
v_plane[uv_index] = v_value.round() as u8;
}
}
}

(y_plane, u_plane, v_plane)
}

fn get_yuv_planes(buffer: &[u8], width: usize, height: usize) -> (&[u8], &[u8], &[u8]) {
// Calculate sizes of Y, U, and V planes for YUV420 format
let y_size = width * height; // Y has full resolution
let uv_width = width / 2; // U and V are subsampled by 2 in both dimensions
let uv_height = height / 2; // U and V are subsampled by 2 in both dimensions
let uv_size = uv_width * uv_height; // Size for U and V planes

// Ensure the buffer has the correct size
// if buffer.len() != y_size + 2 * uv_size {
// panic!("Invalid buffer size for the given width and height!");
// }

// Extract Y, U, and V planes
let y_plane = &buffer[0..y_size]; //.to_vec();
let u_plane = &buffer[y_size..y_size + uv_size]; //.to_vec();
let v_plane = &buffer[y_size + uv_size..]; //.to_vec();

(y_plane, u_plane, v_plane)
}

fn main() -> Result<()> {
let mut height = std::env::var("IMAGE_HEIGHT")
.unwrap_or_else(|_| "480".to_string())
.parse()
.unwrap();
let mut width = std::env::var("IMAGE_WIDTH")
.unwrap_or_else(|_| "640".to_string())
.parse()
.unwrap();
let speed = var("RAV1E_SPEED").map(|s| s.parse().unwrap()).unwrap_or(10);
let mut enc = EncoderConfig {
width,
height,
speed_settings: SpeedSettings::from_preset(speed),
low_latency: true,
..Default::default()
};
let cfg = Config::new().with_encoder_config(enc.clone());
cfg.validate()?;

let (mut node, mut events) =
DoraNode::init_from_env().context("Could not initialize dora node")?;

loop {
match events.recv() {
Some(Event::Input {
id,
data,
mut metadata,
}) => {
if let Some(Parameter::Integer(h)) = metadata.parameters.get("height") {
height = *h as usize;
};
if let Some(Parameter::Integer(w)) = metadata.parameters.get("width") {
width = *w as usize;
};
let encoding = if let Some(Parameter::String(encoding)) =
metadata.parameters.get("encoding")
{
encoding
} else {
"bgr8"
};
enc = EncoderConfig {
width,
height,
speed_settings: SpeedSettings::from_preset(speed),
low_latency: true,
..Default::default()
};
match encoding {
"mono16" => {
enc.bit_depth = 12;
enc.chroma_sampling = color::ChromaSampling::Cs400;
}
_ => {}
}

let cfg = Config::new().with_encoder_config(enc.clone());
if encoding == "bgr8" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer: Vec<u8> = buffer.values().to_vec();
let (y, u, v) = bgr8_to_yuv420(buffer, width, height);

// Transpose values from BGR to RGB
// let buffer: Vec<u8> = buffer.chunks(3).flat_map(|x| [x[2], x[1], x[0]]).collect();

let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
continue;
}
_ => {
warn!("Unable to send frame ");
continue;
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "yuv420" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer = buffer.values(); //.to_vec();

let (y, u, v) = get_yuv_planes(buffer, width, height);
let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
}
_ => {
warn!("Unable to send frame ");
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "mono16" {
let buffer: &UInt16Array = data.as_any().downcast_ref().unwrap();
let buffer: &[u16] = buffer.values();
// let buffer = shift_u16_slice_to_upper_12_bits(buffer);
let bytes: &[u8] = &bytemuck::cast_slice(&buffer);

let mut ctx: Context<u16> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
// Multiply by 2 the stride as it is going to be width * 2 as we're converting 16-bit to 2*8-bit.
f.planes[0].copy_from_raw_u8(bytes, stride * 2, 2);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
}
_ => {
warn!("Unable to send frame ");
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else if encoding == "rgb8" {
let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap();
let buffer: Vec<u8> = buffer.values().to_vec();
let buffer: Vec<u8> =
buffer.chunks(3).flat_map(|x| [x[2], x[1], x[0]]).collect();
let (y, u, v) = bgr8_to_yuv420(buffer, width, height);

// Transpose values from BGR to RGB

let mut ctx: Context<u8> = cfg.new_context().unwrap();
let mut f = ctx.new_frame();

let xdec = f.planes[0].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[0].copy_from_raw_u8(&y, stride, 1);
let xdec = f.planes[1].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[1].copy_from_raw_u8(&u, stride, 1);
let xdec = f.planes[2].cfg.xdec;
let stride = (width + xdec) >> xdec;
f.planes[2].copy_from_raw_u8(&v, stride, 1);

match ctx.send_frame(f) {
Ok(_) => {}
Err(e) => match e {
EncoderStatus::EnoughData => {
warn!("Unable to send frame ");
continue;
}
_ => {
warn!("Unable to send frame ");
continue;
}
},
}
metadata
.parameters
.insert("encoding".to_string(), Parameter::String("av1".to_string()));
ctx.flush();
match ctx.receive_packet() {
Ok(pkt) => {
let data = pkt.data;
let arrow = data.into_arrow();
node.send_output(id, metadata.parameters, arrow)
.context("could not send output")
.unwrap();
}
Err(e) => match e {
EncoderStatus::LimitReached => {}
EncoderStatus::Encoded => {}
EncoderStatus::NeedMoreData => {}
_ => {
panic!("Unable to receive packet",);
}
},
}
} else {
unimplemented!("We haven't worked on additional encodings.");
}
}
Some(Event::Error(_e)) => {
continue;
}
_ => break,
};
}

Ok(())
fn main() -> eyre::Result<()> {
dora_rav1e::lib_main()
}

+ 1
- 1
node-hub/dora-rdt-1b/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-rdt-1b"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
description = "Dora Node for RDT 1B"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-reachy2/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-reachy2"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Your Name", email = "email@email.com" }]
description = "dora-reachy2"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-sam2/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-sam2"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Your Name", email = "email@email.com" }]
description = "dora-sam2"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-ugv/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-ugv"
version = "0.3.10"
version = "0.3.11"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
description = "Dora Node for using Agilex UGV"
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-vad/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-vad"
version = "0.3.10"
version = "0.3.11"
description = "Dora Node for Text translating using Argostranslate"
authors = [{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" }]
license = { text = "MIT" }


+ 1
- 1
node-hub/dora-yolo/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "dora-yolo"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/llama-factory-recorder/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "llama-factory-recorder"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/opencv-plot/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "opencv-plot"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/opencv-video-capture/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "opencv-video-capture"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/pyarrow-assert/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "pyarrow-assert"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/pyarrow-sender/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "pyarrow-sender"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


+ 1
- 1
node-hub/terminal-input/pyproject.toml View File

@@ -1,6 +1,6 @@
[project]
name = "terminal-input"
version = "0.3.10"
version = "0.3.11"
authors = [
{ name = "Haixuan Xavier Tao", email = "tao.xavier@outlook.com" },
{ name = "Enzo Le Van", email = "dev@enzo-le-van.fr" },


Loading…
Cancel
Save