### Install rvideo-view using Cargo Source: https://github.com/roboplc/rvideo/blob/main/rvideo-view/README.md This command installs the rvideo-view application using the Cargo package manager. Ensure you have Rust and Cargo installed on your system. ```bash cargo install rvideo-view ``` -------------------------------- ### RVideo Pixel Format Examples in Rust Source: https://context7.com/roboplc/rvideo/llms.txt Demonstrates the usage of different pixel formats available in the RVideo library, including Luma, LumaA, Rgb, Rgba, and MJpeg. It also shows how to calculate buffer sizes for common resolutions. ```rust use rvideo::Format; fn main() { // Grayscale formats let luma8 = Format::Luma8; // 8-bit grayscale, 1 byte/pixel let luma16 = Format::Luma16; // 16-bit grayscale, 2 bytes/pixel let lumaa8 = Format::LumaA8; // 8-bit grayscale + alpha, 2 bytes/pixel let lumaa16 = Format::LumaA16; // 16-bit grayscale + alpha, 4 bytes/pixel // Color formats let rgb8 = Format::Rgb8; // 24-bit RGB, 3 bytes/pixel let rgb16 = Format::Rgb16; // 48-bit RGB, 6 bytes/pixel let rgba8 = Format::Rgba8; // 32-bit RGBA, 4 bytes/pixel let rgba16 = Format::Rgba16; // 64-bit RGBA, 8 bytes/pixel // Compressed format let mjpeg = Format::MJpeg; // Motion JPEG, variable size // Calculate buffer sizes for 640x480 let width = 640u32; let height = 480u32; let rgb8_size = width * height * 3; // 921,600 bytes let rgba8_size = width * height * 4; // 1,228,800 bytes let luma8_size = width * height * 1; // 307,200 bytes println!("RGB8 buffer: {} bytes", rgb8_size); println!("RGBA8 buffer: {} bytes", rgba8_size); println!("Luma8 buffer: {} bytes", luma8_size); } ``` -------------------------------- ### Rust: Default Server Setup and Frame Sending Source: https://context7.com/roboplc/rvideo/llms.txt Demonstrates setting up the default RVideo server, registering a stream, and sending frames from a separate thread. It uses a TCP-based protocol to stream video frames. ```rust use std::{sync::Arc, thread, time::Duration}; use rvideo::{Format, Frame}; fn main() -> Result<(), Box> { // Register a 640x480 RGB8 stream with the default server let stream = rvideo::add_stream(Format::Rgb8, 640, 480)?; // Spawn frame generation thread thread::spawn(move || { loop { // Create frame data (640 * 480 * 3 bytes for RGB8) let frame_data: Vec = vec![0u8; 640 * 480 * 3]; // Send frame using stream helper stream.send_frame(Frame::new(Arc::new(frame_data))).unwrap(); // Or send using stream ID directly // rvideo::send_frame(0, Frame::from(frame_data)).unwrap(); thread::sleep(Duration::from_millis(33)); // ~30 FPS } }); // Start server on TCP port 3001 (blocking) rvideo::serve("127.0.0.1:3001")?; Ok(()) } ``` -------------------------------- ### Rust: Custom Server Instance with Multiple Streams Source: https://context7.com/roboplc/rvideo/llms.txt Illustrates creating a custom RVideo `Server` instance with configurable timeouts and client limits. It shows how to add multiple streams with different formats and send frames to them. ```rust use std::{thread, time::Duration}; use rvideo::{Format, Frame, Server}; fn main() -> Result<(), Box> { // Create custom server with 5-second timeout let server = Server::new(Duration::from_secs(5)); // Limit concurrent client connections (default is 16) server.set_max_clients(4); // Add multiple streams let stream_rgb = server.add_stream(Format::Rgb8, 640, 480)?; let stream_mjpeg = server.add_stream(Format::MJpeg, 1920, 1080)?; println!("Stream RGB ID: {}", stream_rgb.id()); // Output: 0 println!("Stream MJPEG ID: {}", stream_mjpeg.id()); // Output: 1 // Frame generation thread thread::spawn(move || { loop { // Send RGB frames to stream 0 let rgb_data = vec![128u8; 640 * 480 * 3]; stream_rgb.send_frame(Frame::from(rgb_data)).unwrap(); // Send JPEG frames to stream 1 let jpeg_data = std::fs::read("frame.jpg").unwrap_or_default(); stream_mjpeg.send_frame(Frame::from(jpeg_data)).unwrap(); thread::sleep(Duration::from_millis(100)); } }); // Start serving (blocking) server.serve("0.0.0.0:3001")?; Ok(()) } ``` -------------------------------- ### Usage of rvideo-view Source: https://github.com/roboplc/rvideo/blob/main/rvideo-view/README.md This command demonstrates how to run rvideo-view to view an RVideo stream. Replace IP:PORT with the actual IP address and port of the stream. Optional arguments like --max-fps, --timeout, and --stream-id can be used to configure the viewer. ```bash rvideo-view IP:PORT --max-fps --timeout --stream-id ``` -------------------------------- ### Accessing Stream Metadata with RVideo Client (Rust) Source: https://context7.com/roboplc/rvideo/llms.txt Demonstrates how to connect to an RVideo client, select a stream, and access its metadata such as ID, format, width, and height. It also shows how to calculate the expected frame size based on the stream's format and dimensions. Dependencies include `rvideo` and `std::time::Duration`. ```rust use std::time::Duration; use rvideo::{Client, Format}; fn main() -> Result<(), Box> { let mut client = Client::connect("127.0.0.1:3001", Duration::from_secs(5))?; // StreamInfo is returned when selecting a stream let info = client.select_stream(0, 30)?; // Access stream properties let stream_id: u16 = info.id; let format: Format = info.format; let width: u16 = info.width; let height: u16 = info.height; // Display formatted output println!("{}", info); // "#0, WxH: 640x480, Fmt: Rgb8" // Calculate expected frame size based on format let bytes_per_pixel = match format { Format::Luma8 => 1, Format::Luma16 => 2, Format::LumaA8 => 2, Format::LumaA16 => 4, Format::Rgb8 => 3, Format::Rgb16 => 6, Format::Rgba8 => 4, Format::Rgba16 => 8, Format::MJpeg => 0, // Variable size }; if bytes_per_pixel > 0 { let expected_size = (width as usize) * (height as usize) * bytes_per_pixel; println!("Expected frame size: {} bytes", expected_size); } Ok(()) } ``` -------------------------------- ### Rust: Creating RVideo Frames with Metadata Source: https://context7.com/roboplc/rvideo/llms.txt Demonstrates how to create RVideo `Frame` objects, including simple frames from `Vec` or `Arc>`, and frames with MessagePack-encoded metadata. ```rust use std::sync::Arc; use rvideo::Frame; use serde::Serialize; #[derive(Serialize)] struct FrameMetadata { timestamp: u64, camera_id: String, } fn main() { // Simple frame from Vec let raw_data = vec![0u8; 640 * 480 * 3]; let frame1 = Frame::from(raw_data); // Frame from Arc> (zero-copy for shared data) let shared_data = Arc::new(vec![0u8; 640 * 480 * 3]); let frame2 = Frame::new(shared_data); // Frame with MessagePack-encoded metadata let metadata = FrameMetadata { timestamp: 1234567890, camera_id: "cam01".to_string(), }; let meta_bytes = rmp_serde::to_vec_named(&metadata).unwrap(); let image_data = vec![0u8; 640 * 480 * 3]; let frame3 = Frame::new_with_metadata( Arc::new(meta_bytes), Arc::new(image_data), ); } ``` -------------------------------- ### ClientAsync: Asynchronous RVideo Client in Rust with Tokio Source: https://context7.com/roboplc/rvideo/llms.txt Provides an asynchronous client in Rust using Tokio for receiving video frames. Requires the `async` feature to be enabled in Cargo.toml. It connects asynchronously, selects streams, and reads frames within an async loop, suitable for non-blocking applications. ```rust use std::{sync::Arc, time::Duration}; use rvideo::ClientAsync; #[tokio::main] async fn main() -> Result<(), Box> { // Connect asynchronously with timeout let mut client = ClientAsync::connect("127.0.0.1:3001", Duration::from_secs(5)).await?; // Check available streams println!("Streams available: {}", client.streams_available()); // Select stream with max 5 FPS let info = client.select_stream(0, 5).await?; println!("Connected to stream: {}x{} {:?}", info.width, info.height, info.format); // Read frames in async loop let mut frame_count = 0; while let Ok(frame) = client.read_next().await { println!("Received frame {}: {} bytes", frame_count, frame.data.len()); // Process metadata if let Some(meta) = &frame.metadata { let value: serde_json::Value = rmp_serde::from_slice(meta)?; println!("Metadata: {:?}", value); } // Process frame data let data: Vec = Arc::try_unwrap(frame.data).unwrap(); // ... process data ... frame_count += 1; if frame_count >= 50 { break; } } Ok(()) } ``` -------------------------------- ### RVideo Client and Server Error Handling in Rust Source: https://context7.com/roboplc/rvideo/llms.txt Illustrates how to handle various errors that can occur during RVideo client operations, such as connection failures, API version mismatches, and stream selection issues. It also covers server-side errors like too many streams or frame data exceeding limits. ```rust use std::time::Duration; use rvideo::{Client, Error, Format, Frame}; fn handle_client_errors() { match Client::connect("127.0.0.1:3001", Duration::from_secs(5)) { Ok(mut client) => { match client.select_stream(99, 30) { Ok(info) => println!("Connected: {}", info), Err(Error::InvalidStream) => eprintln!("Stream 99 does not exist"), Err(Error::NotReady) => eprintln!("Client not ready"), Err(e) => eprintln!("Stream selection error: {}", e), } } Err(Error::Io(e)) => eprintln!("Connection failed: {}", e), Err(Error::ApiVersion(v)) => eprintln!("Server API version {} not supported", v), Err(Error::InvalidAddress) => eprintln!("Invalid server address"), Err(e) => eprintln!("Connection error: {}", e), } } fn handle_server_errors() -> Result<(), Error> { // Too many streams (max 65535) // Error::TooManyStreams // Invalid stream ID when sending // Error::InvalidStream // Frame data exceeds u32::MAX let huge_data = vec![0u8; u32::MAX as usize + 1]; let result = rvideo::send_frame(0, Frame::from(huge_data)); // Returns Error::FrameDataTooLarge Ok(()) } ``` -------------------------------- ### BoundingBox: Rust Struct for Object Detection Annotations Source: https://context7.com/roboplc/rvideo/llms.txt Defines the BoundingBox struct in Rust for standardized object detection annotations, including position, dimensions, color, confidence, and label. It is recognized by the rvideo-view client and uses a builder pattern for easy creation. The struct is serializable for data transfer. ```rust use std::sync::Arc; use rvideo::{BoundingBox, Frame}; use serde::Serialize; #[derive(Serialize)] struct DetectionFrame { source: String, frame_number: u64, #[serde(rename = ".bboxes")] // Special key for rvideo-view bounding_boxes: Vec, } fn main() { // Create bounding boxes with builder pattern let detections = vec![ BoundingBox::new(100, 200, 50, 80) // x, y, width, height .with_color([255, 0, 0]) // Red RGB .with_label("person") .with_confidence(0.95), BoundingBox::new(300, 150, 120, 60) .with_color([0, 255, 0]) // Green (default) .with_label("car") .with_confidence(0.87), BoundingBox::new(50, 50, 30, 30), // Basic box, green, no label ]; let metadata = DetectionFrame { source: "camera_front".to_string(), frame_number: 42, bounding_boxes: detections, }; // Encode metadata as MessagePack for rvideo-view compatibility let meta_bytes = rmp_serde::to_vec_named(&metadata).unwrap(); let image_data = vec![0u8; 640 * 480 * 3]; let frame = Frame::new_with_metadata( Arc::new(meta_bytes), Arc::new(image_data), ); } ``` -------------------------------- ### Client: Synchronous RVideo Client in Rust Source: https://context7.com/roboplc/rvideo/llms.txt Implements a synchronous client in Rust to connect to an RVideo server. It allows selecting a stream with FPS limiting and receiving frames as an iterator, suitable for sequential frame processing. Includes error handling for connection and stream selection. ```rust use std::{sync::Arc, time::Duration}; use rvideo::Client; fn main() -> Result<(), Box> { // Connect with 5-second timeout let mut client = Client::connect("127.0.0.1:3001", Duration::from_secs(5))?; // Check available streams println!("Streams available: {}", client.streams_available()); // Select stream 0, limit to 10 FPS let info = client.select_stream(0, 10)?; println!("Stream: {}", info); // Output: "#0, WxH: 640x480, Fmt: Rgb8" println!("Format: {:?}", info.format); println!("Dimensions: {}x{}", info.width, info.height); // Iterate over received frames for (count, result) in client.enumerate() { let frame = result?; println!("Frame {}: {} bytes", count, frame.data.len()); // Access metadata if present if let Some(meta) = &frame.metadata { let json: serde_json::Value = rmp_serde::from_slice(meta)?; println!("Metadata: {}", json); } // Access raw frame data let data: Vec = Arc::try_unwrap(frame.data).unwrap(); // Save as image using the `image` crate // let img = image::ImageBuffer::, _>::from_vec( // info.width.into(), info.height.into(), data // ).unwrap(); // img.save(format!("frame_{}.png", count))?; if count >= 100 { break; } } Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.