| @@ -251,10 +251,16 @@ impl Daemon { | |||||
| None => None, | None => None, | ||||
| }; | }; | ||||
| let mut zenoh_config = match std::env::var(zenoh::Config::DEFAULT_CONFIG_PATH_ENV) { | |||||
| Ok(path) => zenoh::Config::from_file(&path) | |||||
| .map_err(|e| eyre!(e)) | |||||
| .wrap_err_with(|| format!("failed to read zenoh config from {path}"))?, | |||||
| let zenoh_session = match std::env::var(zenoh::Config::DEFAULT_CONFIG_PATH_ENV) { | |||||
| Ok(path) => { | |||||
| let zenoh_config = zenoh::Config::from_file(&path) | |||||
| .map_err(|e| eyre!(e)) | |||||
| .wrap_err_with(|| format!("failed to read zenoh config from {path}"))?; | |||||
| zenoh::open(zenoh_config) | |||||
| .await | |||||
| .map_err(|e| eyre!(e)) | |||||
| .context("failed to open zenoh session")? | |||||
| } | |||||
| Err(std::env::VarError::NotPresent) => { | Err(std::env::VarError::NotPresent) => { | ||||
| let mut zenoh_config = zenoh::Config::default(); | let mut zenoh_config = zenoh::Config::default(); | ||||
| @@ -266,24 +272,36 @@ impl Daemon { | |||||
| ) | ) | ||||
| .unwrap(); | .unwrap(); | ||||
| zenoh_config | zenoh_config | ||||
| .insert_json5( | |||||
| "listen/endpoints", | |||||
| r#"{ router: ["tcp/[::]:7447"], peer: ["tcp/[::]:0", "tcp/[::]:5456"] }"#, | |||||
| ) | |||||
| .unwrap(); | |||||
| .insert_json5( | |||||
| "listen/endpoints", | |||||
| r#"{ router: ["tcp/[::]:7447"], peer: ["tcp/[::]:5456"] }"#, | |||||
| ) | |||||
| .unwrap(); | |||||
| zenoh_config | |||||
| .insert_json5("routing/peer", r#"{ mode: "linkstate" }"#) | |||||
| .unwrap(); | |||||
| if cfg!(not(target_os = "linux")) { | |||||
| warn!("disabling multicast on non-linux systems. Enable it with the ZENOH_CONFIG env variable or file"); | |||||
| zenoh_config | |||||
| .insert_json5("scouting/multicast", r#"{ enabled: false }"#) | |||||
| .unwrap(); | |||||
| } | |||||
| }; | }; | ||||
| zenoh_config | |||||
| if let Ok(zenoh_session) = zenoh::open(zenoh_config).await { | |||||
| zenoh_session | |||||
| } else { | |||||
| warn!("failed to open zenoh session, retrying with default config"); | |||||
| zenoh::open(zenoh::Config::default()) | |||||
| .await | |||||
| .map_err(|e| eyre!(e)) | |||||
| .wrap_err("failed to open zenoh session")? | |||||
| } | |||||
| } | } | ||||
| Err(std::env::VarError::NotUnicode(_)) => eyre::bail!( | Err(std::env::VarError::NotUnicode(_)) => eyre::bail!( | ||||
| "{} env variable is not valid unicode", | "{} env variable is not valid unicode", | ||||
| zenoh::Config::DEFAULT_CONFIG_PATH_ENV | zenoh::Config::DEFAULT_CONFIG_PATH_ENV | ||||
| ), | ), | ||||
| }; | }; | ||||
| let zenoh_session = zenoh::open(zenoh_config) | |||||
| .await | |||||
| .map_err(|e| eyre!(e)) | |||||
| .context("failed to open zenoh session")?; | |||||
| let (dora_events_tx, dora_events_rx) = mpsc::channel(5); | let (dora_events_tx, dora_events_rx) = mpsc::channel(5); | ||||
| let daemon = Self { | let daemon = Self { | ||||
| logger: Logger { | logger: Logger { | ||||
| @@ -11,3 +11,4 @@ log = "0.4" | |||||
| structopt = "0.3" | structopt = "0.3" | ||||
| dora-node-api = { workspace = true, features = ["tracing"] } | dora-node-api = { workspace = true, features = ["tracing"] } | ||||
| eyre = "0.6.8" | eyre = "0.6.8" | ||||
| bytemuck = "1.7.0" | |||||
| @@ -9,42 +9,29 @@ nodes: | |||||
| outputs: | outputs: | ||||
| - image | - image | ||||
| env: | env: | ||||
| CAPTURE_PATH: 0 | |||||
| CAPTURE_PATH: 1 | |||||
| IMAGE_WIDTH: 640 | IMAGE_WIDTH: 640 | ||||
| IMAGE_HEIGHT: 480 | IMAGE_HEIGHT: 480 | ||||
| ENCODING: yuv420 | |||||
| - id: camera2 | |||||
| path: dora-pyrealsense | |||||
| _unstable_deploy: | |||||
| machine: encoder | |||||
| inputs: | |||||
| tick: dora/timer/millis/10 | |||||
| outputs: | |||||
| - image | |||||
| env: | |||||
| IMAGE_WIDTH: 640 | |||||
| IMAGE_HEIGHT: 480 | |||||
| ENCODING: jpeg | |||||
| - id: echo | - id: echo | ||||
| build: pip install -e ../../node-hub/dora-echo | build: pip install -e ../../node-hub/dora-echo | ||||
| path: dora-echo | path: dora-echo | ||||
| _unstable_deploy: | _unstable_deploy: | ||||
| machine: decoder | machine: decoder | ||||
| inputs: | |||||
| image: camera2/image | |||||
| #inputs: | |||||
| # image: camera/image | |||||
| outputs: | outputs: | ||||
| - image | - image | ||||
| - id: rav1e-local | - id: rav1e-local | ||||
| path: dora-av1-encoder | |||||
| build: cargo build -p dora-av1-encoder --release | |||||
| path: dora-rav1e | |||||
| build: cargo build -p dora-rav1e --release | |||||
| _unstable_deploy: | _unstable_deploy: | ||||
| machine: encoder | machine: encoder | ||||
| #inputs: | |||||
| # image: camera/image | |||||
| inputs: | |||||
| image: camera/image | |||||
| outputs: | outputs: | ||||
| - frame | |||||
| - image | |||||
| env: | env: | ||||
| IMAGE_WIDTH: 640 | IMAGE_WIDTH: 640 | ||||
| IMAGE_HEIGHT: 480 | IMAGE_HEIGHT: 480 | ||||
| @@ -55,22 +42,22 @@ nodes: | |||||
| _unstable_deploy: | _unstable_deploy: | ||||
| machine: decoder | machine: decoder | ||||
| inputs: | inputs: | ||||
| image: av-local/frame | |||||
| image: rav1e-local/image | |||||
| outputs: | outputs: | ||||
| - frame | |||||
| - image | |||||
| env: | env: | ||||
| IMAGE_WIDTH: 640 | IMAGE_WIDTH: 640 | ||||
| IMAGE_HEIGHT: 480 | IMAGE_HEIGHT: 480 | ||||
| - id: rav1e-remote | - id: rav1e-remote | ||||
| path: dora-av1-encoder | |||||
| build: cargo build -p dora-av1-encoder --release | |||||
| path: dora-rav1e | |||||
| build: cargo build -p dora-rav1e --release | |||||
| _unstable_deploy: | _unstable_deploy: | ||||
| machine: decoder | machine: decoder | ||||
| inputs: | inputs: | ||||
| image: dav1d-remote/image | image: dav1d-remote/image | ||||
| outputs: | outputs: | ||||
| - frame | |||||
| - image | |||||
| env: | env: | ||||
| IMAGE_WIDTH: 640 | IMAGE_WIDTH: 640 | ||||
| IMAGE_HEIGHT: 480 | IMAGE_HEIGHT: 480 | ||||
| @@ -79,11 +66,11 @@ nodes: | |||||
| path: dora-dav1d | path: dora-dav1d | ||||
| build: cargo build -p dora-dav1d --release | build: cargo build -p dora-dav1d --release | ||||
| _unstable_deploy: | _unstable_deploy: | ||||
| machine: decoder | |||||
| machine: encoder | |||||
| inputs: | inputs: | ||||
| image: rav1e-local/frame | |||||
| image: rav1e-remote/image | |||||
| outputs: | outputs: | ||||
| - frame | |||||
| - image | |||||
| env: | env: | ||||
| IMAGE_WIDTH: 640 | IMAGE_WIDTH: 640 | ||||
| IMAGE_HEIGHT: 480 | IMAGE_HEIGHT: 480 | ||||
| @@ -94,14 +81,14 @@ nodes: | |||||
| machine: encoder | machine: encoder | ||||
| path: dora-rerun | path: dora-rerun | ||||
| inputs: | inputs: | ||||
| image: dav1d-local/frame | |||||
| # image: echo/image | |||||
| image_decode: dav1d-local/image | |||||
| image_echo: echo/image | |||||
| #image_2: camera6/image | #image_2: camera6/image | ||||
| - id: plot2 | |||||
| build: pip install -e ../../node-hub/opencv-plot | |||||
| _unstable_deploy: | |||||
| machine: encoder | |||||
| path: opencv-plot | |||||
| inputs: | |||||
| image: echo/image | |||||
| # - id: plot2 | |||||
| # build: pip install -e ../../node-hub/opencv-plot | |||||
| # _unstable_deploy: | |||||
| # machine: encoder | |||||
| # path: opencv-plot | |||||
| # inputs: | |||||
| # image: echo/image | |||||
| @@ -41,7 +41,6 @@ fn main() -> Result<()> { | |||||
| let mut settings = Settings::new(); | let mut settings = Settings::new(); | ||||
| // settings.set_n_threads(16); | // settings.set_n_threads(16); | ||||
| settings.set_max_frame_delay(1); | settings.set_max_frame_delay(1); | ||||
| let mut dec = | let mut dec = | ||||
| dav1d::Decoder::with_settings(&settings).expect("failed to create decoder instance"); | dav1d::Decoder::with_settings(&settings).expect("failed to create decoder instance"); | ||||
| @@ -78,17 +77,34 @@ fn main() -> Result<()> { | |||||
| } else { | } else { | ||||
| 480 | 480 | ||||
| }; | }; | ||||
| 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, width, 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(); | |||||
| 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, width, 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; | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,7 +9,7 @@ | |||||
| use std::env::var; | use std::env::var; | ||||
| use dora_node_api::arrow::array::UInt8Array; | |||||
| use dora_node_api::arrow::array::{UInt16Array, UInt8Array}; | |||||
| use dora_node_api::{DoraNode, Event, IntoArrow, Parameter}; | use dora_node_api::{DoraNode, Event, IntoArrow, Parameter}; | ||||
| use eyre::{Context as EyreContext, Result}; | use eyre::{Context as EyreContext, Result}; | ||||
| use log::warn; | use log::warn; | ||||
| @@ -119,6 +119,14 @@ fn main() -> Result<()> { | |||||
| low_latency: true, | low_latency: true, | ||||
| ..Default::default() | ..Default::default() | ||||
| }; | }; | ||||
| match encoding { | |||||
| "mono16" => { | |||||
| enc.bit_depth = 12; | |||||
| enc.chroma_sampling = color::ChromaSampling::Cs400; | |||||
| } | |||||
| _ => {} | |||||
| } | |||||
| let cfg = Config::new().with_encoder_config(enc.clone()); | let cfg = Config::new().with_encoder_config(enc.clone()); | ||||
| if encoding == "bgr8" { | if encoding == "bgr8" { | ||||
| let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap(); | let buffer: &UInt8Array = data.as_any().downcast_ref().unwrap(); | ||||
| @@ -192,6 +200,48 @@ fn main() -> Result<()> { | |||||
| let stride = (width + xdec) >> xdec; | let stride = (width + xdec) >> xdec; | ||||
| f.planes[2].copy_from_raw_u8(&v, stride, 1); | 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",); | |||||
| } | |||||
| }, | |||||
| } | |||||
| vec![] | |||||
| } else if encoding == "mono16" { | |||||
| let buffer: &UInt16Array = data.as_any().downcast_ref().unwrap(); | |||||
| let buffer: &[u16] = buffer.values(); | |||||
| let mut ctx: Context<u16> = cfg.new_context().unwrap(); | |||||
| let mut f = ctx.new_frame(); | |||||
| let origin = f.planes[0].data_origin_mut(); | |||||
| origin.copy_from_slice(buffer); | |||||
| match ctx.send_frame(f) { | match ctx.send_frame(f) { | ||||
| Ok(_) => {} | Ok(_) => {} | ||||
| Err(e) => match e { | Err(e) => match e { | ||||