From eae753462dd43f0ce127f82f6ae5ff047baa4aa6 Mon Sep 17 00:00:00 2001 From: Cody Morgan Date: Wed, 26 Jul 2023 21:49:29 -0400 Subject: [PATCH 1/2] initial request info about onvif back channel audio --- examples/client/src/info.rs | 1 + src/client/mod.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/examples/client/src/info.rs b/examples/client/src/info.rs index 5007f38..097c213 100644 --- a/examples/client/src/info.rs +++ b/examples/client/src/info.rs @@ -25,6 +25,7 @@ pub async fn run(opts: Opts) -> Result<(), Error> { let session = retina::client::Session::describe( opts.src.url.clone(), retina::client::SessionOptions::default() + .back_channel(true) .creds(creds) .user_agent("Retina sdp example".to_owned()), ) diff --git a/src/client/mod.rs b/src/client/mod.rs index 932132d..3b14bba 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -505,6 +505,7 @@ pub struct SessionOptions { teardown: TeardownPolicy, unassigned_channel_data: UnassignedChannelDataPolicy, session_id: SessionIdPolicy, + back_channel: bool, } /// Policy for handling data received on unassigned RTSP interleaved channels. @@ -709,6 +710,11 @@ impl SessionOptions { self } + pub fn back_channel(mut self, back_channel: bool) -> Self { + self.back_channel = back_channel; + self + } + pub fn session_id(mut self, policy: SessionIdPolicy) -> Self { self.session_id = policy; self @@ -1498,8 +1504,12 @@ impl Session { ) -> Result { let mut req = rtsp_types::Request::builder(Method::Describe, rtsp_types::Version::V1_0) .header(rtsp_types::headers::ACCEPT, "application/sdp") - .request_uri(url.clone()) - .build(Bytes::new()); + .request_uri(url.clone()); + if options.back_channel{ + req= req.header(rtsp_types::headers::REQUIRE, "www.onvif.org/ver20/backchannel"); + } + + let mut req = req.build(Bytes::new()); let mut requested_auth = None; let (msg_ctx, cseq, response) = conn .send( From 400e48f700e694e55552740cae0e316ba5456e1a Mon Sep 17 00:00:00 2001 From: Cody Morgan Date: Tue, 2 Jan 2024 11:12:28 -0500 Subject: [PATCH 2/2] pencil in SendingPacket and StreamDirection --- src/client/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ src/client/parse.rs | 7 ++++++- src/rtp.rs | 15 +++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 3b14bba..26ff5ee 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -25,6 +25,7 @@ use url::Url; use crate::client::parse::SessionHeader; use crate::codec::CodecItem; +use crate::rtp::SendingPacket; use crate::{ Error, ErrorInt, RtspMessageContext, StreamContext, StreamContextInner, TcpStreamContext, UdpStreamContext, @@ -845,6 +846,13 @@ impl std::ops::Deref for Tool { } } +//enum sending or Receiving +#[derive(Copy, Clone, Debug)] +pub enum StreamDirection{ + Receiving, + Sending, +} + /// Information about a stream offered within a presentation. /// /// Currently if multiple formats are offered, this only describes the first. @@ -860,6 +868,7 @@ pub struct Stream { channels: Option, framerate: Option, control: Option, + direction: StreamDirection } impl std::fmt::Debug for Stream { @@ -872,6 +881,7 @@ impl std::fmt::Debug for Stream { .field("clock_rate", &self.clock_rate_hz) .field("channels", &self.channels) .field("framerate", &self.framerate) + .field("direction", &self.direction) .field("depacketizer", &self.depacketizer) .field("state", &self.state) .finish() @@ -939,6 +949,10 @@ impl Stream { pub fn control(&self) -> Option<&Url> { self.control.as_ref() } + + pub fn direction(&self) -> StreamDirection { + self.direction + } } struct UdpSockets { @@ -2542,6 +2556,28 @@ impl PinnedDrop for SessionInner { } } +impl futures::Sink for Session{ + type Error = futures::io::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn start_send(self: Pin<&mut Self>, item: SendingPacket) -> Result<(), Self::Error> { + //self.0.conn.as_mut().unwrap().inner.send(item); + Ok(()) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } +} + + impl futures::Stream for Session { type Item = Result; diff --git a/src/client/parse.rs b/src/client/parse.rs index eb8ab14..59afb99 100644 --- a/src/client/parse.rs +++ b/src/client/parse.rs @@ -7,7 +7,7 @@ use sdp_types::Media; use std::{net::IpAddr, num::NonZeroU16}; use url::Url; -use super::{Presentation, Stream}; +use super::{Presentation, Stream, StreamDirection}; /// A static payload type in the [RTP parameters /// registry](https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-1). @@ -257,6 +257,7 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result { @@ -313,6 +314,9 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result { + direction=StreamDirection::Sending; + } _ => (), } } @@ -376,6 +380,7 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result, +} + +impl std::fmt::Debug for SendingPacket { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SendingPacket") + .field("streamId", &self.stream_id) + .field("payload_type", &self.raw.payload_type()) + .finish() + } +} + /// A received RTP packet. /// /// This holds more information than the packet itself: also a