diff --git a/CHANGELOG.md b/CHANGELOG.md index f9c24a4..665919c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,12 @@ Likewise `retina::codec::CodecItem`. * minimum Rust version is now 1.56. +## `v0.3.10` (2022-05-09) + +* ignore unparseable `rtptime` values in the `PLAY` response's `RTP-Info` header. + This improves compatibility with the OMNY M5S2A 2812 camera, as described in + [scottlamb/moonfire-nvr#224](https://github.com/scottlamb/moonfire-nvr/issues/224). + ## `v0.3.9` (2022-04-12) * camera interop: eliminate `bad clockrate in rtpmap` errors with cameras that diff --git a/src/client/parse.rs b/src/client/parse.rs index 56af658..a541a34 100644 --- a/src/client/parse.rs +++ b/src/client/parse.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use bytes::Bytes; -use log::debug; +use log::{debug, warn}; use sdp_types::Media; use std::{net::IpAddr, num::NonZeroU16}; use url::Url; @@ -646,11 +646,10 @@ pub(crate) fn parse_play( .map_err(|_| format!("bad seq {:?}", value))?; state.initial_seq = Some(seq); } - "rtptime" => { - let rtptime = u32::from_str_radix(value, 10) - .map_err(|_| format!("bad rtptime {:?}", value))?; - state.initial_rtptime = Some(rtptime); - } + "rtptime" => match u32::from_str_radix(value, 10) { + Ok(v) => state.initial_rtptime = Some(v), + Err(_) => warn!("Unparseable rtptime in RTP-Info header {:?}", rtp_info), + }, "ssrc" => { let ssrc = u32::from_str_radix(value, 16) .map_err(|_| format!("Unparseable ssrc {}", value))?; @@ -1068,6 +1067,32 @@ mod tests { }; } + /// Simulates a negative `rtptime` value in the `PLAY` response, as returned by the OMNY M5S2A + /// 2812 in [scottlamb/moonfire-nvr#224](https://github.com/scottlamb/moonfire-nvr/issues/224). + /// + /// The rest of the data is copied from the `bunny` test above. + /// + /// This is currently treated as if the `rtptime` parameter were absent. + #[test] + fn bad_rtptime() { + let prefix = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; + let mut p = parse_describe(prefix, include_bytes!("testdata/bunny_describe.txt")).unwrap(); + p.streams[0].state = dummy_stream_state_init(None); + super::parse_play( + &response(include_bytes!("testdata/bad_rtptime.txt")), + &mut p, + ) + .unwrap(); + match &p.streams[0].state { + StreamState::Init(state) => { + assert_eq!(state.initial_rtptime, None); + assert_eq!(state.initial_seq, Some(1)); + assert_eq!(state.ssrc, None); + } + _ => panic!(), + }; + } + #[test] fn foscam() { // DESCRIBE. diff --git a/src/client/testdata/bad_rtptime.txt b/src/client/testdata/bad_rtptime.txt new file mode 100644 index 0000000..1aff116 --- /dev/null +++ b/src/client/testdata/bad_rtptime.txt @@ -0,0 +1,9 @@ +RTSP/1.0 200 OK +Notes: copied from bunny_play.txt; modified to simulate a bad rtptime value as in https://github.com/scottlamb/moonfire-nvr/issues/224 +RTP-Info: url=trackID=1;seq=1;rtptime=-1,url=rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov/trackID=2;seq=1;rtptime=-1 +CSeq: 3 +Server: Wowza Streaming Engine 4.8.10 build20210217143515 +Cache-Control: no-cache +Range: npt=0.0-596.48 +Session: 551045787;timeout=60 +