2021-06-04 03:26:45 +04:00
|
|
|
// Copyright (C) 2021 Scott Lamb <slamb@slamb.org>
|
|
|
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
|
|
|
2021-07-08 21:52:39 +04:00
|
|
|
use anyhow::{anyhow, Error};
|
2021-06-04 03:26:45 +04:00
|
|
|
use futures::StreamExt;
|
2021-09-10 07:00:42 +04:00
|
|
|
use log::{error, info};
|
|
|
|
use retina::client::SessionGroup;
|
2021-06-04 03:26:45 +04:00
|
|
|
use retina::codec::CodecItem;
|
2021-09-10 07:00:42 +04:00
|
|
|
use std::sync::Arc;
|
2021-06-04 03:26:45 +04:00
|
|
|
|
|
|
|
#[derive(structopt::StructOpt)]
|
|
|
|
pub struct Opts {
|
|
|
|
#[structopt(flatten)]
|
|
|
|
src: super::Source,
|
|
|
|
}
|
|
|
|
|
2021-12-28 16:41:30 +04:00
|
|
|
pub async fn run(opts: Opts, is_info: bool) -> Result<(), Error> {
|
2021-09-10 07:00:42 +04:00
|
|
|
let session_group = Arc::new(SessionGroup::default());
|
2021-12-28 16:41:30 +04:00
|
|
|
let r = run_inner(opts, session_group.clone(), is_info).await;
|
2021-09-10 07:00:42 +04:00
|
|
|
if let Err(e) = session_group.await_teardown().await {
|
|
|
|
error!("TEARDOWN failed: {}", e);
|
|
|
|
}
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
2022-01-10 21:06:05 +04:00
|
|
|
async fn run_inner(
|
|
|
|
opts: Opts,
|
|
|
|
session_group: Arc<SessionGroup>,
|
|
|
|
is_info: bool,
|
|
|
|
) -> Result<(), Error> {
|
2021-06-04 03:26:45 +04:00
|
|
|
let stop = tokio::signal::ctrl_c();
|
|
|
|
|
|
|
|
let creds = super::creds(opts.src.username, opts.src.password);
|
2021-08-19 23:56:54 +04:00
|
|
|
let mut session = retina::client::Session::describe(
|
|
|
|
opts.src.url,
|
|
|
|
retina::client::SessionOptions::default()
|
|
|
|
.creds(creds)
|
2021-09-10 07:00:42 +04:00
|
|
|
.user_agent("Retina metadata example".to_owned())
|
|
|
|
.session_group(session_group),
|
2021-08-19 23:56:54 +04:00
|
|
|
)
|
|
|
|
.await?;
|
2021-12-28 16:41:30 +04:00
|
|
|
if is_info {
|
|
|
|
for stream in session.streams() {
|
|
|
|
println!("{}", stream);
|
|
|
|
}
|
|
|
|
return Ok(());
|
|
|
|
}
|
2021-06-04 03:26:45 +04:00
|
|
|
let onvif_stream_i = session
|
|
|
|
.streams()
|
|
|
|
.iter()
|
|
|
|
.position(|s| matches!(s.parameters(), Some(retina::codec::Parameters::Message(..))))
|
2021-07-08 21:52:39 +04:00
|
|
|
.ok_or_else(|| anyhow!("couldn't find onvif stream"))?;
|
2021-06-04 03:26:45 +04:00
|
|
|
session.setup(onvif_stream_i).await?;
|
2021-08-28 03:30:55 +04:00
|
|
|
let mut session = session
|
2021-08-19 23:56:54 +04:00
|
|
|
.play(retina::client::PlayOptions::default().ignore_zero_seq(true))
|
2021-06-04 03:26:45 +04:00
|
|
|
.await?
|
|
|
|
.demuxed()?;
|
|
|
|
|
|
|
|
tokio::pin!(stop);
|
|
|
|
loop {
|
|
|
|
tokio::select! {
|
|
|
|
item = session.next() => {
|
2021-07-08 21:52:39 +04:00
|
|
|
match item.ok_or_else(|| anyhow!("EOF"))?? {
|
2021-06-04 03:26:45 +04:00
|
|
|
CodecItem::MessageFrame(m) => {
|
|
|
|
info!("{}: {}\n", &m.timestamp, std::str::from_utf8(&m.data[..]).unwrap());
|
|
|
|
},
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
_ = &mut stop => {
|
|
|
|
break;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|