Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
joaoantoniocardoso committed Nov 6, 2024
1 parent d4e2cd3 commit 880de74
Show file tree
Hide file tree
Showing 26 changed files with 717 additions and 475 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/src/html/vue.js
/target
**/*.rs.bk
.vscode
logs
13 changes: 3 additions & 10 deletions src/lib/controls/onvif/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use onvif_schema::{devicemgmt::GetDeviceInformationResponse, transport};
use anyhow::{anyhow, Result};
use tracing::*;

use crate::video::types::{Format, VideoEncodeType};
use crate::{stream::gst::utils::get_encode_from_rtspsrc, video::types::Format};

#[derive(Clone)]
pub struct OnvifCamera {
Expand Down Expand Up @@ -149,15 +149,8 @@ impl OnvifCamera {
continue;
};

let encode = match &video_encoder_configuration.encoding {
onvif_schema::onvif::VideoEncoding::H264 => VideoEncodeType::H264,
onvif_schema::onvif::VideoEncoding::__Unknown__(encoding) if encoding == "H265" => {
VideoEncodeType::H265
}
_unsupported => {
warn!("Skipping unsupported encoding: {_unsupported:?}");
continue;
}
let Some(encode) = get_encode_from_rtspsrc(&stream_uri).await else {
continue;
};

let video_rate = video_encoder_configuration
Expand Down
46 changes: 33 additions & 13 deletions src/lib/controls/onvif/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,22 @@ impl Default for Manager {
impl Manager {
// Construct our manager, should be done inside main
#[instrument(level = "trace")]
pub fn init() {
pub async fn init() {
MANAGER.as_ref();

let manager = MANAGER.write().await;

let mut mcontext = manager.mcontext.write().await;

// todo: fill MANAGER.context.credentials with credentials passed by ENV and CLI
// It can be in the form of "<USER>:<PWD>@<IP>", but we need to escape special characters need to.
let _ = mcontext.credentials.insert(
"192.168.0.168".to_string(),
Arc::new(RwLock::new(Credentials {
username: "admin".to_string(),
password: "12345".to_string(),
})),
);
}

#[instrument(level = "trace", skip(context))]
Expand All @@ -71,7 +83,7 @@ impl Manager {

onvif::discovery::DiscoveryBuilder::default()
.listen_address(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
.duration(tokio::time::Duration::from_secs(5))
.duration(tokio::time::Duration::from_secs(20))
.run()
.await?
.for_each_concurrent(MAX_CONCURRENT_JUMPERS, |device| {
Expand All @@ -80,14 +92,22 @@ impl Manager {
async move {
trace!("Device found: {device:#?}");

let credentials = context
.read()
.await
.credentials
.get(&device.address)
.map(|c| c.blocking_read().clone());

for url in device.urls {
let host = url
.host()
.map(|host| host.to_string())
.unwrap_or(url.to_string());

let credentials = if let Some(credentials) =
context.read().await.credentials.get(&host)
{
Some(credentials.read().await.clone())
} else {
None
};

trace!("Device {host}. Using credentials: {credentials:?}");

let camera = match OnvifCamera::try_new(&Auth {
credentials: credentials.clone(),
url: url.clone(),
Expand All @@ -96,7 +116,7 @@ impl Manager {
{
Ok(camera) => camera,
Err(error) => {
error!("Failed creating camera: {error:#?}");
error!(host, "Failed creating camera: {error:?}");
return;
}
};
Expand All @@ -105,20 +125,20 @@ impl Manager {
{
Ok(streams_informations) => streams_informations,
Err(error) => {
error!("Failed getting stream uris: {error:#?}");
error!(host, "Failed getting stream information: {error}");
continue;
}
};

trace!("Found streams {streams_informations:?}");
trace!(host, "Found streams {streams_informations:?}");

let mut context = context.write().await;
for stream_information in streams_informations {
context
.cameras
.entry(stream_information.stream_uri.clone())
.or_insert_with(|| {
debug!("New stream inserted: {stream_information:?}");
debug!(host, "New stream inserted: {stream_information:?}");

camera.clone()
});
Expand Down
239 changes: 138 additions & 101 deletions src/lib/custom/bluerov.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
use tracing::*;
use url::Url;

use crate::network::utils::get_visible_qgc_address;
use crate::stream::types::*;
use crate::video::{self, types::*, video_source::VideoSourceAvailable};
use crate::video_stream::types::VideoAndStreamInformation;
use tracing::*;
use crate::{
network::utils::get_visible_qgc_address,
stream::types::*,
video::{
self,
types::*,
video_source::{CamerasAvailable, VideoSourceFormats},
},
video_stream::types::VideoAndStreamInformation,
};

fn get_cameras_with_encode_type(encode: VideoEncodeType) -> Vec<VideoSourceType> {
let cameras = video::video_source_local::VideoSourceLocal::cameras_available();
cameras
.iter()
.filter(move |cam| {
cam.inner()
.formats()
.iter()
.any(|format| format.encode == encode)
})
.cloned()
.collect()
async fn get_cameras_with_encode_type(encode: VideoEncodeType) -> Vec<VideoSourceType> {
let mut result = Vec::new();

let cameras = video::video_source_local::VideoSourceLocal::cameras_available().await;

for camera in cameras.iter() {
if camera
.formats()
.await
.iter()
.any(|format| format.encode == encode)
{
result.push(camera.clone());
}
}

result
}

fn sort_sizes(sizes: &mut [Size]) {
Expand All @@ -27,91 +38,117 @@ fn sort_sizes(sizes: &mut [Size]) {
});
}

pub fn udp() -> Vec<VideoAndStreamInformation> {
get_cameras_with_encode_type(VideoEncodeType::H264)
.iter()
.enumerate()
.filter_map(|(index, cam)| {
let formats = cam.inner().formats();
let Some(format) = formats
.iter()
.find(|format| format.encode == VideoEncodeType::H264)
else {
warn!("Unable to find a valid format for {cam:?}");
return None;
};

// Get the biggest resolution possible
let mut sizes = format.sizes.clone();
sort_sizes(&mut sizes);

let Some(size) = sizes.last() else {
warn!("Unable to find a valid size for {cam:?}");
return None;
};

Some(VideoAndStreamInformation {
name: format!("UDP Stream {}", index),
stream_information: StreamInformation {
endpoints: vec![
Url::parse(&format!("udp://192.168.2.1:{}", 5600 + index)).ok()?
],
configuration: CaptureConfiguration::Video(VideoCaptureConfiguration {
encode: format.encode.clone(),
height: size.height,
width: size.width,
frame_interval: size.intervals.first()?.clone(),
}),
extended_configuration: None,
},
video_source: cam.clone(),
})
pub async fn udp() -> Vec<VideoAndStreamInformation> {
let mut result = Vec::new();

let sources = get_cameras_with_encode_type(VideoEncodeType::H264).await;

for (index, source) in sources.iter().enumerate() {
let formats = source.formats().await;

let Some(format) = formats
.iter()
.find(|format| format.encode == VideoEncodeType::H264)
else {
warn!("Unable to find a valid format for {source:?}");
continue;
};

// Get the biggest resolution possible
let mut sizes = format.sizes.clone();
sort_sizes(&mut sizes);
let Some(size) = sizes.last() else {
warn!("Unable to find a valid size for {source:?}");
continue;
};

let Some(frame_interval) = size.intervals.first().cloned() else {
warn!("Unable to find a frame interval");
continue;
};

let endpoint = match Url::parse(&format!("udp://192.168.2.1:{}", 5600 + index)) {
Ok(url) => url,
Err(error) => {
warn!("Failed to parse URL: {error:?}");
continue;
}
};

result.push(VideoAndStreamInformation {
name: format!("UDP Stream {index}"),
stream_information: StreamInformation {
endpoints: vec![endpoint],
configuration: CaptureConfiguration::Video(VideoCaptureConfiguration {
encode: format.encode.clone(),
height: size.height,
width: size.width,
frame_interval,
}),
extended_configuration: None,
},
video_source: source.clone(),
})
.collect()
}

result
}

pub fn rtsp() -> Vec<VideoAndStreamInformation> {
get_cameras_with_encode_type(VideoEncodeType::H264)
.iter()
.enumerate()
.filter_map(|(index, cam)| {
let formats = cam.inner().formats();
let Some(format) = formats
.iter()
.find(|format| format.encode == VideoEncodeType::H264)
else {
warn!("Unable to find a valid format for {cam:?}");
return None;
};

// Get the biggest resolution possible
let mut sizes = format.sizes.clone();
sort_sizes(&mut sizes);

let Some(size) = sizes.last() else {
warn!("Unable to find a valid size for {cam:?}");
return None;
};

let visible_qgc_ip_address = get_visible_qgc_address();

Some(VideoAndStreamInformation {
name: format!("RTSP Stream {index}"),
stream_information: StreamInformation {
endpoints: vec![Url::parse(&format!(
"rtsp://{visible_qgc_ip_address}:8554/video_{index}"
))
.ok()?],
configuration: CaptureConfiguration::Video(VideoCaptureConfiguration {
encode: format.encode.clone(),
height: size.height,
width: size.width,
frame_interval: size.intervals.first()?.clone(),
}),
extended_configuration: None,
},
video_source: cam.clone(),
})
})
.collect()
pub async fn rtsp() -> Vec<VideoAndStreamInformation> {
let mut result = Vec::new();

let sources = get_cameras_with_encode_type(VideoEncodeType::H264).await;

for (index, source) in sources.iter().enumerate() {
let formats = source.formats().await;

let Some(format) = formats
.iter()
.find(|format| format.encode == VideoEncodeType::H264)
else {
warn!("Unable to find a valid format for {source:?}");
continue;
};

// Get the biggest resolution possible
let mut sizes = format.sizes.clone();
sort_sizes(&mut sizes);
let Some(size) = sizes.last() else {
warn!("Unable to find a valid size for {source:?}");
continue;
};

let Some(frame_interval) = size.intervals.first().cloned() else {
warn!("Unable to find a frame interval");
continue;
};

let visible_qgc_ip_address = get_visible_qgc_address();
let endpoint = match Url::parse(&format!(
"rtsp://{visible_qgc_ip_address}:8554/video_{index}"
)) {
Ok(url) => url,
Err(error) => {
warn!("Failed to parse URL: {error:?}");
continue;
}
};

result.push(VideoAndStreamInformation {
name: format!("RTSP Stream {index}"),
stream_information: StreamInformation {
endpoints: vec![endpoint],
configuration: CaptureConfiguration::Video(VideoCaptureConfiguration {
encode: format.encode.clone(),
height: size.height,
width: size.width,
frame_interval,
}),
extended_configuration: None,
},
video_source: source.clone(),
});
}

result
}
Loading

0 comments on commit 880de74

Please sign in to comment.