cargo clippy --fix
This upgrades to using the inline format args syntax.
This commit is contained in:
parent
74ff5de837
commit
489c29b797
@ -92,7 +92,7 @@ fn make_test_data(max_payload_size: u16) -> Bytes {
|
|||||||
data.push(b'$'); // interleaved data
|
data.push(b'$'); // interleaved data
|
||||||
data.push(0); // channel 0
|
data.push(0); // channel 0
|
||||||
data.extend_from_slice(&u16::try_from(pkt.len()).unwrap().to_be_bytes()[..]);
|
data.extend_from_slice(&u16::try_from(pkt.len()).unwrap().to_be_bytes()[..]);
|
||||||
data.extend_from_slice(&pkt);
|
data.extend_from_slice(pkt);
|
||||||
}
|
}
|
||||||
timestamp = timestamp.try_add(3000).unwrap();
|
timestamp = timestamp.try_add(3000).unwrap();
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ async fn read_to_eof(addr: SocketAddr) {
|
|||||||
while let Some(item) = session.next().await {
|
while let Some(item) = session.next().await {
|
||||||
match item {
|
match item {
|
||||||
Ok(CodecItem::VideoFrame(_)) => i += 1,
|
Ok(CodecItem::VideoFrame(_)) => i += 1,
|
||||||
o => panic!("bad item: {:#?}", o),
|
o => panic!("bad item: {o:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(i, 30 * 60);
|
assert_eq!(i, 30 * 60);
|
||||||
|
@ -17,7 +17,7 @@ const BUNNY: &[u8] = include_bytes!("bunny.rtsp");
|
|||||||
|
|
||||||
// TODO: it'd be nice to have a slick way of loading saved RTSP flows for testing.
|
// TODO: it'd be nice to have a slick way of loading saved RTSP flows for testing.
|
||||||
// For now, this builds state via several internal interfaces.
|
// For now, this builds state via several internal interfaces.
|
||||||
fn h264_aac<F: FnMut(CodecItem) -> ()>(mut f: F) {
|
fn h264_aac<F: FnMut(CodecItem)>(mut f: F) {
|
||||||
let mut remaining = BUNNY;
|
let mut remaining = BUNNY;
|
||||||
let mut timelines = [
|
let mut timelines = [
|
||||||
Timeline::new(Some(0), 12_000, None).unwrap(),
|
Timeline::new(Some(0), 12_000, None).unwrap(),
|
||||||
@ -91,7 +91,7 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
CodecItem::VideoFrame(v) => v,
|
CodecItem::VideoFrame(v) => v,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
w.write_all(&v.data()[..]).unwrap();
|
w.write_all(v.data()).unwrap();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -51,12 +51,11 @@ impl ChannelMappings {
|
|||||||
/// Assigns an even channel id (to RTP) and its odd successor (to RTCP) or errors.
|
/// Assigns an even channel id (to RTP) and its odd successor (to RTCP) or errors.
|
||||||
pub fn assign(&mut self, channel_id: u8, stream_i: usize) -> Result<(), String> {
|
pub fn assign(&mut self, channel_id: u8, stream_i: usize) -> Result<(), String> {
|
||||||
if (channel_id & 1) != 0 {
|
if (channel_id & 1) != 0 {
|
||||||
return Err(format!("Can't assign odd channel id {}", channel_id));
|
return Err(format!("Can't assign odd channel id {channel_id}"));
|
||||||
}
|
}
|
||||||
if stream_i >= 255 {
|
if stream_i >= 255 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Can't assign channel to stream id {} because it's >= 255",
|
"Can't assign channel to stream id {stream_i} because it's >= 255"
|
||||||
stream_i
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let i = usize::from(channel_id >> 1);
|
let i = usize::from(channel_id >> 1);
|
||||||
|
@ -331,8 +331,7 @@ impl std::str::FromStr for TeardownPolicy {
|
|||||||
"never" => TeardownPolicy::Never,
|
"never" => TeardownPolicy::Never,
|
||||||
"always" => TeardownPolicy::Always,
|
"always" => TeardownPolicy::Always,
|
||||||
_ => bail!(ErrorInt::InvalidArgument(format!(
|
_ => bail!(ErrorInt::InvalidArgument(format!(
|
||||||
"bad TeardownPolicy {}; expected auto, never, or always",
|
"bad TeardownPolicy {s}; expected auto, never, or always"
|
||||||
s
|
|
||||||
))),
|
))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -389,9 +388,8 @@ impl std::str::FromStr for InitialTimestampPolicy {
|
|||||||
"ignore" => InitialTimestampPolicy::Ignore,
|
"ignore" => InitialTimestampPolicy::Ignore,
|
||||||
"permissive" => InitialTimestampPolicy::Permissive,
|
"permissive" => InitialTimestampPolicy::Permissive,
|
||||||
_ => bail!(ErrorInt::InvalidArgument(format!(
|
_ => bail!(ErrorInt::InvalidArgument(format!(
|
||||||
"bad InitialTimestampPolicy {}; \
|
"bad InitialTimestampPolicy {s}; \
|
||||||
expected default, require, ignore or permissive",
|
expected default, require, ignore or permissive"
|
||||||
s
|
|
||||||
))),
|
))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -478,9 +476,8 @@ impl std::str::FromStr for UnassignedChannelDataPolicy {
|
|||||||
"error" => UnassignedChannelDataPolicy::Error,
|
"error" => UnassignedChannelDataPolicy::Error,
|
||||||
"ignore" => UnassignedChannelDataPolicy::Ignore,
|
"ignore" => UnassignedChannelDataPolicy::Ignore,
|
||||||
_ => bail!(ErrorInt::InvalidArgument(format!(
|
_ => bail!(ErrorInt::InvalidArgument(format!(
|
||||||
"bad UnassignedChannelDataPolicy {}; expected auto, assume-stale-session, error, \
|
"bad UnassignedChannelDataPolicy {s}; expected auto, assume-stale-session, error, \
|
||||||
or ignore",
|
or ignore"
|
||||||
s
|
|
||||||
))),
|
))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -528,9 +525,8 @@ impl std::str::FromStr for Transport {
|
|||||||
"tcp" => Transport::Tcp(TcpTransportOptions::default()),
|
"tcp" => Transport::Tcp(TcpTransportOptions::default()),
|
||||||
"udp" => Transport::Udp(UdpTransportOptions::default()),
|
"udp" => Transport::Udp(UdpTransportOptions::default()),
|
||||||
_ => bail!(ErrorInt::InvalidArgument(format!(
|
_ => bail!(ErrorInt::InvalidArgument(format!(
|
||||||
"bad Transport {}; \
|
"bad Transport {s}; \
|
||||||
expected tcp or udp",
|
expected tcp or udp"
|
||||||
s
|
|
||||||
))),
|
))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1100,7 +1096,7 @@ impl RtspConnection {
|
|||||||
msg_ctx: self.inner.eof_ctx(),
|
msg_ctx: self.inner.eof_ctx(),
|
||||||
source: std::io::Error::new(
|
source: std::io::Error::new(
|
||||||
std::io::ErrorKind::UnexpectedEof,
|
std::io::ErrorKind::UnexpectedEof,
|
||||||
format!("EOF while expecting response to {} CSeq {}", method, cseq),
|
format!("EOF while expecting response to {method} CSeq {cseq}"),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
@ -1146,8 +1142,7 @@ impl RtspConnection {
|
|||||||
conn_ctx: *self.inner.ctx(),
|
conn_ctx: *self.inner.ctx(),
|
||||||
msg_ctx,
|
msg_ctx,
|
||||||
description: format!(
|
description: format!(
|
||||||
"Expected response to {} CSeq {}, got {}",
|
"Expected response to {method} CSeq {cseq}, got {description}",
|
||||||
method, cseq, description,
|
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1195,7 +1190,7 @@ impl RtspConnection {
|
|||||||
method: req.method().clone(),
|
method: req.method().clone(),
|
||||||
cseq,
|
cseq,
|
||||||
status: resp.status(),
|
status: resp.status(),
|
||||||
description: format!("Can't understand WWW-Authenticate header: {}", e),
|
description: format!("Can't understand WWW-Authenticate header: {e}"),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
continue;
|
continue;
|
||||||
@ -1919,8 +1914,7 @@ impl Session<Playing> {
|
|||||||
source: std::io::Error::new(
|
source: std::io::Error::new(
|
||||||
std::io::ErrorKind::TimedOut,
|
std::io::ErrorKind::TimedOut,
|
||||||
format!(
|
format!(
|
||||||
"Unable to write keepalive {} within {:?}",
|
"Unable to write keepalive {cseq} within {keepalive_interval:?}",
|
||||||
cseq, keepalive_interval,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
@ -1930,8 +1924,7 @@ impl Session<Playing> {
|
|||||||
source: std::io::Error::new(
|
source: std::io::Error::new(
|
||||||
std::io::ErrorKind::TimedOut,
|
std::io::ErrorKind::TimedOut,
|
||||||
format!(
|
format!(
|
||||||
"Server failed to respond to keepalive {} within {:?}",
|
"Server failed to respond to keepalive {cseq} within {keepalive_interval:?}",
|
||||||
cseq, keepalive_interval,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
@ -2038,7 +2031,7 @@ impl Session<Playing> {
|
|||||||
.inner
|
.inner
|
||||||
.ctx(),
|
.ctx(),
|
||||||
msg_ctx: *msg_ctx,
|
msg_ctx: *msg_ctx,
|
||||||
description: format!("Unexpected RTSP response {:#?}", response),
|
description: format!("Unexpected RTSP response {response:#?}"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2620,9 +2613,9 @@ mod tests {
|
|||||||
Some(Ok(PacketItem::Rtp(p))) => {
|
Some(Ok(PacketItem::Rtp(p))) => {
|
||||||
assert_eq!(p.ssrc(), 0xdcc4a0d8);
|
assert_eq!(p.ssrc(), 0xdcc4a0d8);
|
||||||
assert_eq!(p.sequence_number(), 0x41d4);
|
assert_eq!(p.sequence_number(), 0x41d4);
|
||||||
assert_eq!(&p.payload()[..], b"hello world");
|
assert_eq!(p.payload(), b"hello world");
|
||||||
}
|
}
|
||||||
o => panic!("unexpected item: {:#?}", o),
|
o => panic!("unexpected item: {o:#?}"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async {
|
async {
|
||||||
@ -2669,8 +2662,7 @@ mod tests {
|
|||||||
let elapsed = tokio::time::Instant::now() - drop_time;
|
let elapsed = tokio::time::Instant::now() - drop_time;
|
||||||
assert!(
|
assert!(
|
||||||
elapsed < std::time::Duration::from_secs(60),
|
elapsed < std::time::Duration::from_secs(60),
|
||||||
"elapsed={:?}",
|
"elapsed={elapsed:?}"
|
||||||
elapsed
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2731,9 +2723,9 @@ mod tests {
|
|||||||
Some(Ok(PacketItem::Rtp(p))) => {
|
Some(Ok(PacketItem::Rtp(p))) => {
|
||||||
assert_eq!(p.ssrc(), 0xdcc4a0d8);
|
assert_eq!(p.ssrc(), 0xdcc4a0d8);
|
||||||
assert_eq!(p.sequence_number(), 0x41d4);
|
assert_eq!(p.sequence_number(), 0x41d4);
|
||||||
assert_eq!(&p.payload()[..], b"hello world");
|
assert_eq!(p.payload(), b"hello world");
|
||||||
}
|
}
|
||||||
o => panic!("unexpected item: {:#?}", o),
|
o => panic!("unexpected item: {o:#?}"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async {
|
async {
|
||||||
@ -2768,8 +2760,7 @@ mod tests {
|
|||||||
let elapsed = tokio::time::Instant::now() - drop_time;
|
let elapsed = tokio::time::Instant::now() - drop_time;
|
||||||
assert!(
|
assert!(
|
||||||
elapsed >= std::time::Duration::from_secs(60),
|
elapsed >= std::time::Duration::from_secs(60),
|
||||||
"elapsed={:?}",
|
"elapsed={elapsed:?}"
|
||||||
elapsed
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2815,8 +2806,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
elapsed >= std::time::Duration::from_secs(LIVE555_EXPIRATION_SEC),
|
elapsed >= std::time::Duration::from_secs(LIVE555_EXPIRATION_SEC),
|
||||||
"elapsed={:?}",
|
"elapsed={elapsed:?}"
|
||||||
elapsed
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2893,7 +2883,7 @@ mod tests {
|
|||||||
("Demuxed", std::mem::size_of::<Demuxed>()),
|
("Demuxed", std::mem::size_of::<Demuxed>()),
|
||||||
("Stream", std::mem::size_of::<Stream>()),
|
("Stream", std::mem::size_of::<Stream>()),
|
||||||
] {
|
] {
|
||||||
println!("{:-40} {:4}", name, size);
|
println!("{name:-40} {size:4}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,8 +207,7 @@ fn join_control(base_url: &Url, control: &str) -> Result<Url, String> {
|
|||||||
))
|
))
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"unable to join base url {} with control url {:?}: {}",
|
"unable to join base url {base_url} with control url {control:?}: {e}"
|
||||||
base_url, control, e
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -247,9 +246,9 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result<Stream, Stri
|
|||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let rtp_payload_type = u8::from_str_radix(rtp_payload_type_str, 10)
|
let rtp_payload_type = u8::from_str_radix(rtp_payload_type_str, 10)
|
||||||
.map_err(|_| format!("invalid RTP payload type {:?}", rtp_payload_type_str))?;
|
.map_err(|_| format!("invalid RTP payload type {rtp_payload_type_str:?}"))?;
|
||||||
if (rtp_payload_type & 0x80) != 0 {
|
if (rtp_payload_type & 0x80) != 0 {
|
||||||
return Err(format!("invalid RTP payload type {}", rtp_payload_type));
|
return Err(format!("invalid RTP payload type {rtp_payload_type}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture interesting attributes.
|
// Capture interesting attributes.
|
||||||
@ -342,7 +341,7 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result<Stream, Stri
|
|||||||
u16::from_str_radix(c, 10)
|
u16::from_str_radix(c, 10)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(NonZeroU16::new)
|
.and_then(NonZeroU16::new)
|
||||||
.ok_or_else(|| format!("Invalid channels specification {:?}", c))
|
.ok_or_else(|| format!("Invalid channels specification {c:?}"))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
}
|
}
|
||||||
@ -352,8 +351,7 @@ fn parse_media(base_url: &Url, media_description: &Media) -> Result<Stream, Stri
|
|||||||
.and_then(Option::as_ref)
|
.and_then(Option::as_ref)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
format!(
|
format!(
|
||||||
"Expected rtpmap parameter or assigned static payload type (got {})",
|
"Expected rtpmap parameter or assigned static payload type (got {rtp_payload_type})"
|
||||||
rtp_payload_type
|
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
encoding_name = type_.encoding;
|
encoding_name = type_.encoding;
|
||||||
@ -402,7 +400,7 @@ impl<'a> std::fmt::Debug for MostlyAscii<'a> {
|
|||||||
b'\r' => write!(f, "\\r")?,
|
b'\r' => write!(f, "\\r")?,
|
||||||
// Note this writes newlines in unescaped form.
|
// Note this writes newlines in unescaped form.
|
||||||
b' ' | b'\n' | 0x20..=0x7E => write!(f, "{}", b as char)?,
|
b' ' | b'\n' | 0x20..=0x7E => write!(f, "{}", b as char)?,
|
||||||
_ => write!(f, "\\x{:02X}", b)?,
|
_ => write!(f, "\\x{b:02X}")?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(f, "\"")?;
|
write!(f, "\"")?;
|
||||||
@ -426,7 +424,7 @@ pub(crate) fn parse_describe(
|
|||||||
|
|
||||||
let raw_sdp = MostlyAscii(&response.body()[..]);
|
let raw_sdp = MostlyAscii(&response.body()[..]);
|
||||||
let sdp = sdp_types::Session::parse(raw_sdp.0)
|
let sdp = sdp_types::Session::parse(raw_sdp.0)
|
||||||
.map_err(|e| format!("Unable to parse SDP: {}\n\n{:#?}", e, raw_sdp,))?;
|
.map_err(|e| format!("Unable to parse SDP: {e}\n\n{raw_sdp:#?}",))?;
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc2326#appendix-C.1.1
|
// https://tools.ietf.org/html/rfc2326#appendix-C.1.1
|
||||||
let base_url = response
|
let base_url = response
|
||||||
@ -437,7 +435,7 @@ pub(crate) fn parse_describe(
|
|||||||
.header(&rtsp_types::headers::CONTENT_LOCATION)
|
.header(&rtsp_types::headers::CONTENT_LOCATION)
|
||||||
.map(|v| (rtsp_types::headers::CONTENT_LOCATION, v))
|
.map(|v| (rtsp_types::headers::CONTENT_LOCATION, v))
|
||||||
})
|
})
|
||||||
.map(|(h, v)| Url::parse(v.as_str()).map_err(|e| format!("bad {} {:?}: {}", h, v, e)))
|
.map(|(h, v)| Url::parse(v.as_str()).map_err(|e| format!("bad {h} {v:?}: {e}")))
|
||||||
.unwrap_or_else(|| Ok(request_url.clone()))?;
|
.unwrap_or_else(|| Ok(request_url.clone()))?;
|
||||||
|
|
||||||
let mut control = None;
|
let mut control = None;
|
||||||
@ -538,7 +536,7 @@ pub(crate) fn parse_setup(response: &rtsp_types::Response<Bytes>) -> Result<Setu
|
|||||||
Some((id, timeout_str)) => {
|
Some((id, timeout_str)) => {
|
||||||
if let Some(v) = timeout_str.trim().strip_prefix("timeout=") {
|
if let Some(v) = timeout_str.trim().strip_prefix("timeout=") {
|
||||||
let timeout_sec =
|
let timeout_sec =
|
||||||
u32::from_str_radix(v, 10).map_err(|_| format!("Unparseable timeout {}", v))?;
|
u32::from_str_radix(v, 10).map_err(|_| format!("Unparseable timeout {v}"))?;
|
||||||
|
|
||||||
if timeout_sec == 0 {
|
if timeout_sec == 0 {
|
||||||
// This would make Retina send keepalives at an absurd rate; reject.
|
// This would make Retina send keepalives at an absurd rate; reject.
|
||||||
@ -565,25 +563,25 @@ pub(crate) fn parse_setup(response: &rtsp_types::Response<Bytes>) -> Result<Setu
|
|||||||
let mut server_port = None;
|
let mut server_port = None;
|
||||||
for part in transport.as_str().split(';') {
|
for part in transport.as_str().split(';') {
|
||||||
if let Some(v) = part.strip_prefix("ssrc=") {
|
if let Some(v) = part.strip_prefix("ssrc=") {
|
||||||
let v = u32::from_str_radix(v, 16).map_err(|_| format!("Unparseable ssrc {}", v))?;
|
let v = u32::from_str_radix(v, 16).map_err(|_| format!("Unparseable ssrc {v}"))?;
|
||||||
ssrc = Some(v);
|
ssrc = Some(v);
|
||||||
break;
|
break;
|
||||||
} else if let Some(interleaved) = part.strip_prefix("interleaved=") {
|
} else if let Some(interleaved) = part.strip_prefix("interleaved=") {
|
||||||
let mut channels = interleaved.splitn(2, '-');
|
let mut channels = interleaved.splitn(2, '-');
|
||||||
let n = channels.next().expect("splitn returns at least one part");
|
let n = channels.next().expect("splitn returns at least one part");
|
||||||
let n = u8::from_str_radix(n, 10).map_err(|_| format!("bad channel number {}", n))?;
|
let n = u8::from_str_radix(n, 10).map_err(|_| format!("bad channel number {n}"))?;
|
||||||
if let Some(m) = channels.next() {
|
if let Some(m) = channels.next() {
|
||||||
let m = u8::from_str_radix(m, 10)
|
let m = u8::from_str_radix(m, 10)
|
||||||
.map_err(|_| format!("bad second channel number {}", m))?;
|
.map_err(|_| format!("bad second channel number {m}"))?;
|
||||||
if n.checked_add(1) != Some(m) {
|
if n.checked_add(1) != Some(m) {
|
||||||
format!("Expected adjacent channels; got {}-{}", n, m);
|
format!("Expected adjacent channels; got {n}-{m}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channel_id = Some(n);
|
channel_id = Some(n);
|
||||||
} else if let Some(s) = part.strip_prefix("source=") {
|
} else if let Some(s) = part.strip_prefix("source=") {
|
||||||
source = Some(
|
source = Some(
|
||||||
s.parse()
|
s.parse()
|
||||||
.map_err(|_| format!("Transport header has unparseable source {:?}", s))?,
|
.map_err(|_| format!("Transport header has unparseable source {s:?}"))?,
|
||||||
);
|
);
|
||||||
} else if let Some(s) = part.strip_prefix("server_port=") {
|
} else if let Some(s) = part.strip_prefix("server_port=") {
|
||||||
server_port = Some(parse_server_port(s).map_err(|()| {
|
server_port = Some(parse_server_port(s).map_err(|()| {
|
||||||
@ -666,7 +664,7 @@ pub(crate) fn parse_play(
|
|||||||
match key {
|
match key {
|
||||||
"seq" => {
|
"seq" => {
|
||||||
let seq = u16::from_str_radix(value, 10)
|
let seq = u16::from_str_radix(value, 10)
|
||||||
.map_err(|_| format!("bad seq {:?}", value))?;
|
.map_err(|_| format!("bad seq {value:?}"))?;
|
||||||
state.initial_seq = Some(seq);
|
state.initial_seq = Some(seq);
|
||||||
}
|
}
|
||||||
"rtptime" => match u32::from_str_radix(value, 10) {
|
"rtptime" => match u32::from_str_radix(value, 10) {
|
||||||
@ -675,7 +673,7 @@ pub(crate) fn parse_play(
|
|||||||
},
|
},
|
||||||
"ssrc" => {
|
"ssrc" => {
|
||||||
let ssrc = u32::from_str_radix(value, 16)
|
let ssrc = u32::from_str_radix(value, 16)
|
||||||
.map_err(|_| format!("Unparseable ssrc {}", value))?;
|
.map_err(|_| format!("Unparseable ssrc {value}"))?;
|
||||||
state.ssrc = Some(ssrc);
|
state.ssrc = Some(ssrc);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -243,7 +243,7 @@ mod tests {
|
|||||||
pkt.0,
|
pkt.0,
|
||||||
) {
|
) {
|
||||||
Ok(Some(PacketItem::Rtp(_))) => {}
|
Ok(Some(PacketItem::Rtp(_))) => {}
|
||||||
o => panic!("unexpected packet 1 result: {:#?}", o),
|
o => panic!("unexpected packet 1 result: {o:#?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mystery pt=50 packet with same sequence number.
|
// Mystery pt=50 packet with same sequence number.
|
||||||
@ -267,7 +267,7 @@ mod tests {
|
|||||||
pkt.0,
|
pkt.0,
|
||||||
) {
|
) {
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
o => panic!("unexpected packet 2 result: {:#?}", o),
|
o => panic!("unexpected packet 2 result: {o:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ mod tests {
|
|||||||
Ok(Some(PacketItem::Rtp(p))) => {
|
Ok(Some(PacketItem::Rtp(p))) => {
|
||||||
assert_eq!(p.timestamp().elapsed(), 0);
|
assert_eq!(p.timestamp().elapsed(), 0);
|
||||||
}
|
}
|
||||||
o => panic!("unexpected packet 2 result: {:#?}", o),
|
o => panic!("unexpected packet 2 result: {o:#?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pkt, _payload_range) = crate::rtp::RawPacketBuilder {
|
let (pkt, _payload_range) = crate::rtp::RawPacketBuilder {
|
||||||
@ -327,7 +327,7 @@ mod tests {
|
|||||||
pkt.0,
|
pkt.0,
|
||||||
) {
|
) {
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
o => panic!("unexpected packet 1 result: {:#?}", o),
|
o => panic!("unexpected packet 1 result: {o:#?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pkt, _payload_range) = crate::rtp::RawPacketBuilder {
|
let (pkt, _payload_range) = crate::rtp::RawPacketBuilder {
|
||||||
@ -353,7 +353,7 @@ mod tests {
|
|||||||
// The missing timestamp shouldn't have adjusted time.
|
// The missing timestamp shouldn't have adjusted time.
|
||||||
assert_eq!(p.timestamp().elapsed(), 1);
|
assert_eq!(p.timestamp().elapsed(), 1);
|
||||||
}
|
}
|
||||||
o => panic!("unexpected packet 2 result: {:#?}", o),
|
o => panic!("unexpected packet 2 result: {o:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,7 @@ impl Timeline {
|
|||||||
.transpose()
|
.transpose()
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
format!(
|
format!(
|
||||||
"clock_rate={} rejected because max forward jump of {} sec exceeds i32::MAX",
|
"clock_rate={clock_rate} rejected because max forward jump of {MAX_FORWARD_TIME_JUMP_SECS} sec exceeds i32::MAX"
|
||||||
clock_rate, MAX_FORWARD_TIME_JUMP_SECS
|
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.map(|j| NonZeroI32::new(j).expect("non-zero times non-zero must be non-zero"));
|
.map(|j| NonZeroI32::new(j).expect("non-zero times non-zero must be non-zero"));
|
||||||
|
@ -70,12 +70,12 @@ impl AudioSpecificConfig {
|
|||||||
let mut r = bitstream_io::BitReader::endian(raw, bitstream_io::BigEndian);
|
let mut r = bitstream_io::BitReader::endian(raw, bitstream_io::BigEndian);
|
||||||
let audio_object_type = match r
|
let audio_object_type = match r
|
||||||
.read::<u8>(5)
|
.read::<u8>(5)
|
||||||
.map_err(|e| format!("unable to read audio_object_type: {}", e))?
|
.map_err(|e| format!("unable to read audio_object_type: {e}"))?
|
||||||
{
|
{
|
||||||
31 => {
|
31 => {
|
||||||
32 + r
|
32 + r
|
||||||
.read::<u8>(6)
|
.read::<u8>(6)
|
||||||
.map_err(|e| format!("unable to read audio_object_type ext: {}", e))?
|
.map_err(|e| format!("unable to read audio_object_type ext: {e}"))?
|
||||||
}
|
}
|
||||||
o => o,
|
o => o,
|
||||||
};
|
};
|
||||||
@ -83,7 +83,7 @@ impl AudioSpecificConfig {
|
|||||||
// ISO/IEC 14496-3 section 1.6.3.3.
|
// ISO/IEC 14496-3 section 1.6.3.3.
|
||||||
let sampling_frequency = match r
|
let sampling_frequency = match r
|
||||||
.read::<u8>(4)
|
.read::<u8>(4)
|
||||||
.map_err(|e| format!("unable to read sampling_frequency: {}", e))?
|
.map_err(|e| format!("unable to read sampling_frequency: {e}"))?
|
||||||
{
|
{
|
||||||
0x0 => 96_000,
|
0x0 => 96_000,
|
||||||
0x1 => 88_200,
|
0x1 => 88_200,
|
||||||
@ -99,52 +99,52 @@ impl AudioSpecificConfig {
|
|||||||
0xb => 8_000,
|
0xb => 8_000,
|
||||||
0xc => 7_350,
|
0xc => 7_350,
|
||||||
v @ 0xd | v @ 0xe => {
|
v @ 0xd | v @ 0xe => {
|
||||||
return Err(format!("reserved sampling_frequency_index value 0x{:x}", v))
|
return Err(format!("reserved sampling_frequency_index value 0x{v:x}"))
|
||||||
}
|
}
|
||||||
0xf => r
|
0xf => r
|
||||||
.read::<u32>(24)
|
.read::<u32>(24)
|
||||||
.map_err(|e| format!("unable to read sampling_frequency ext: {}", e))?,
|
.map_err(|e| format!("unable to read sampling_frequency ext: {e}"))?,
|
||||||
0x10..=0xff => unreachable!(),
|
0x10..=0xff => unreachable!(),
|
||||||
};
|
};
|
||||||
let channels = {
|
let channels = {
|
||||||
let c = r
|
let c = r
|
||||||
.read::<u8>(4)
|
.read::<u8>(4)
|
||||||
.map_err(|e| format!("unable to read channels: {}", e))?;
|
.map_err(|e| format!("unable to read channels: {e}"))?;
|
||||||
CHANNEL_CONFIGS
|
CHANNEL_CONFIGS
|
||||||
.get(usize::from(c))
|
.get(usize::from(c))
|
||||||
.ok_or_else(|| format!("reserved channelConfiguration 0x{:x}", c))?
|
.ok_or_else(|| format!("reserved channelConfiguration 0x{c:x}"))?
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| "program_config_element parsing unimplemented".to_string())?
|
.ok_or_else(|| "program_config_element parsing unimplemented".to_string())?
|
||||||
};
|
};
|
||||||
if audio_object_type == 5 || audio_object_type == 29 {
|
if audio_object_type == 5 || audio_object_type == 29 {
|
||||||
// extensionSamplingFrequencyIndex + extensionSamplingFrequency.
|
// extensionSamplingFrequencyIndex + extensionSamplingFrequency.
|
||||||
if r.read::<u8>(4)
|
if r.read::<u8>(4)
|
||||||
.map_err(|e| format!("unable to read extensionSamplingFrequencyIndex: {}", e))?
|
.map_err(|e| format!("unable to read extensionSamplingFrequencyIndex: {e}"))?
|
||||||
== 0xf
|
== 0xf
|
||||||
{
|
{
|
||||||
r.skip(24)
|
r.skip(24)
|
||||||
.map_err(|e| format!("unable to read extensionSamplingFrequency: {}", e))?;
|
.map_err(|e| format!("unable to read extensionSamplingFrequency: {e}"))?;
|
||||||
}
|
}
|
||||||
// audioObjectType (a different one) + extensionChannelConfiguration.
|
// audioObjectType (a different one) + extensionChannelConfiguration.
|
||||||
if r.read::<u8>(5)
|
if r.read::<u8>(5)
|
||||||
.map_err(|e| format!("unable to read second audioObjectType: {}", e))?
|
.map_err(|e| format!("unable to read second audioObjectType: {e}"))?
|
||||||
== 22
|
== 22
|
||||||
{
|
{
|
||||||
r.skip(4)
|
r.skip(4)
|
||||||
.map_err(|e| format!("unable to read extensionChannelConfiguration: {}", e))?;
|
.map_err(|e| format!("unable to read extensionChannelConfiguration: {e}"))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The supported types here are the ones that use GASpecificConfig.
|
// The supported types here are the ones that use GASpecificConfig.
|
||||||
match audio_object_type {
|
match audio_object_type {
|
||||||
1 | 2 | 3 | 4 | 6 | 7 | 17 | 19 | 20 | 21 | 22 | 23 => {}
|
1 | 2 | 3 | 4 | 6 | 7 | 17 | 19 | 20 | 21 | 22 | 23 => {}
|
||||||
o => return Err(format!("unsupported audio_object_type {}", o)),
|
o => return Err(format!("unsupported audio_object_type {o}")),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GASpecificConfig, ISO/IEC 14496-3 section 4.4.1.
|
// GASpecificConfig, ISO/IEC 14496-3 section 4.4.1.
|
||||||
let frame_length_flag = r
|
let frame_length_flag = r
|
||||||
.read_bit()
|
.read_bit()
|
||||||
.map_err(|e| format!("unable to read frame_length_flag: {}", e))?;
|
.map_err(|e| format!("unable to read frame_length_flag: {e}"))?;
|
||||||
let frame_length = match (audio_object_type, frame_length_flag) {
|
let frame_length = match (audio_object_type, frame_length_flag) {
|
||||||
(3 /* AAC SR */, false) => NonZeroU16::new(256).expect("non-zero"),
|
(3 /* AAC SR */, false) => NonZeroU16::new(256).expect("non-zero"),
|
||||||
(3 /* AAC SR */, true) => {
|
(3 /* AAC SR */, true) => {
|
||||||
@ -157,7 +157,7 @@ impl AudioSpecificConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc6381#section-3.3
|
// https://datatracker.ietf.org/doc/html/rfc6381#section-3.3
|
||||||
let rfc6381_codec = Some(format!("mp4a.40.{}", audio_object_type));
|
let rfc6381_codec = Some(format!("mp4a.40.{audio_object_type}"));
|
||||||
|
|
||||||
Ok(AudioSpecificConfig {
|
Ok(AudioSpecificConfig {
|
||||||
parameters: AudioParameters {
|
parameters: AudioParameters {
|
||||||
@ -197,7 +197,7 @@ fn set_length(len: usize, data: &mut [u8]) -> Result<usize, String> {
|
|||||||
Ok(4)
|
Ok(4)
|
||||||
} else {
|
} else {
|
||||||
// BaseDescriptor sets a maximum length of 2**28 - 1.
|
// BaseDescriptor sets a maximum length of 2**28 - 1.
|
||||||
Err(format!("length {} too long", len))
|
Err(format!("length {len} too long"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ fn make_sample_entry(
|
|||||||
// version/structure of the AudioSampleEntryBox and the version of the
|
// version/structure of the AudioSampleEntryBox and the version of the
|
||||||
// stsd box. Just support the former for now.
|
// stsd box. Just support the former for now.
|
||||||
let sampling_frequency = u16::try_from(sampling_frequency)
|
let sampling_frequency = u16::try_from(sampling_frequency)
|
||||||
.map_err(|_| format!("aac sampling_frequency={} unsupported", sampling_frequency))?;
|
.map_err(|_| format!("aac sampling_frequency={sampling_frequency} unsupported"))?;
|
||||||
buf.put_u32(u32::from(sampling_frequency) << 16);
|
buf.put_u32(u32::from(sampling_frequency) << 16);
|
||||||
|
|
||||||
// Write the embedded ESDBox (`esds`), as in ISO/IEC 14496-14 section 5.6.1.
|
// Write the embedded ESDBox (`esds`), as in ISO/IEC 14496-14 section 5.6.1.
|
||||||
@ -368,7 +368,7 @@ fn parse_format_specific_params(
|
|||||||
}
|
}
|
||||||
let (key, value) = p
|
let (key, value) = p
|
||||||
.split_once('=')
|
.split_once('=')
|
||||||
.ok_or_else(|| format!("bad format-specific-param {}", p))?;
|
.ok_or_else(|| format!("bad format-specific-param {p}"))?;
|
||||||
match &key.to_ascii_lowercase()[..] {
|
match &key.to_ascii_lowercase()[..] {
|
||||||
"config" => {
|
"config" => {
|
||||||
config = Some(
|
config = Some(
|
||||||
@ -397,13 +397,12 @@ fn parse_format_specific_params(
|
|||||||
}
|
}
|
||||||
// https://datatracker.ietf.org/doc/html/rfc3640#section-3.3.6 AAC-hbr
|
// https://datatracker.ietf.org/doc/html/rfc3640#section-3.3.6 AAC-hbr
|
||||||
if mode != Some("AAC-hbr") {
|
if mode != Some("AAC-hbr") {
|
||||||
return Err(format!("Expected mode AAC-hbr, got {:#?}", mode));
|
return Err(format!("Expected mode AAC-hbr, got {mode:#?}"));
|
||||||
}
|
}
|
||||||
let config = config.ok_or_else(|| "config must be specified".to_string())?;
|
let config = config.ok_or_else(|| "config must be specified".to_string())?;
|
||||||
if size_length != Some(13) || index_length != Some(3) || index_delta_length != Some(3) {
|
if size_length != Some(13) || index_length != Some(3) || index_delta_length != Some(3) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Unexpected sizeLength={:?} indexLength={:?} indexDeltaLength={:?}",
|
"Unexpected sizeLength={size_length:?} indexLength={index_length:?} indexDeltaLength={index_delta_length:?}"
|
||||||
size_length, index_length, index_delta_length
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +551,7 @@ impl Depacketizer {
|
|||||||
|
|
||||||
// AAC-hbr requires 16-bit AU headers: 13-bit size, 3-bit index.
|
// AAC-hbr requires 16-bit AU headers: 13-bit size, 3-bit index.
|
||||||
if (au_headers_length_bits & 0x7) != 0 {
|
if (au_headers_length_bits & 0x7) != 0 {
|
||||||
return Err(format!("bad au-headers-length {}", au_headers_length_bits));
|
return Err(format!("bad au-headers-length {au_headers_length_bits}"));
|
||||||
}
|
}
|
||||||
let au_headers_count = au_headers_length_bits >> 4;
|
let au_headers_count = au_headers_length_bits >> 4;
|
||||||
let data_off = 2 + (usize::from(au_headers_count) << 1);
|
let data_off = 2 + (usize::from(au_headers_count) << 1);
|
||||||
@ -563,8 +562,7 @@ impl Depacketizer {
|
|||||||
DepacketizerState::Fragmented(ref mut frag) => {
|
DepacketizerState::Fragmented(ref mut frag) => {
|
||||||
if au_headers_count != 1 {
|
if au_headers_count != 1 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Got {}-AU packet while fragment in progress",
|
"Got {au_headers_count}-AU packet while fragment in progress"
|
||||||
au_headers_count
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (pkt.timestamp().timestamp as u16) != frag.rtp_timestamp {
|
if (pkt.timestamp().timestamp as u16) != frag.rtp_timestamp {
|
||||||
@ -740,8 +738,7 @@ impl Depacketizer {
|
|||||||
stream_ctx,
|
stream_ctx,
|
||||||
agg,
|
agg,
|
||||||
format!(
|
format!(
|
||||||
"aggregate timestamp {} + {} overflows",
|
"aggregate timestamp {agg_timestamp} + {delta} overflows"
|
||||||
agg_timestamp, delta
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,7 @@ impl Depacketizer {
|
|||||||
pub(super) fn new(clock_rate: u32) -> Result<Self, String> {
|
pub(super) fn new(clock_rate: u32) -> Result<Self, String> {
|
||||||
if clock_rate != FIXED_CLOCK_RATE {
|
if clock_rate != FIXED_CLOCK_RATE {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Expected clock rate of {} for G.723, got {}",
|
"Expected clock rate of {FIXED_CLOCK_RATE} for G.723, got {clock_rate}"
|
||||||
FIXED_CLOCK_RATE, clock_rate
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -103,8 +103,7 @@ impl Depacketizer {
|
|||||||
) -> Result<Self, String> {
|
) -> Result<Self, String> {
|
||||||
if clock_rate != 90_000 {
|
if clock_rate != 90_000 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"invalid H.264 clock rate {}; must always be 90000",
|
"invalid H.264 clock rate {clock_rate}; must always be 90000"
|
||||||
clock_rate
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +135,7 @@ impl Depacketizer {
|
|||||||
pub(super) fn push(&mut self, pkt: ReceivedPacket) -> Result<(), String> {
|
pub(super) fn push(&mut self, pkt: ReceivedPacket) -> Result<(), String> {
|
||||||
// Push shouldn't be called until pull is exhausted.
|
// Push shouldn't be called until pull is exhausted.
|
||||||
if let Some(p) = self.pending.as_ref() {
|
if let Some(p) = self.pending.as_ref() {
|
||||||
panic!("push with data already pending: {:?}", p);
|
panic!("push with data already pending: {p:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut access_unit =
|
let mut access_unit =
|
||||||
@ -231,15 +230,14 @@ impl Depacketizer {
|
|||||||
// https://tools.ietf.org/html/rfc6184#section-5.2
|
// https://tools.ietf.org/html/rfc6184#section-5.2
|
||||||
let nal_header = data[0];
|
let nal_header = data[0];
|
||||||
if (nal_header >> 7) != 0 {
|
if (nal_header >> 7) != 0 {
|
||||||
return Err(format!("NAL header {:02x} has F bit set", nal_header));
|
return Err(format!("NAL header {nal_header:02x} has F bit set"));
|
||||||
}
|
}
|
||||||
data.advance(1); // skip the header byte.
|
data.advance(1); // skip the header byte.
|
||||||
match nal_header & 0b11111 {
|
match nal_header & 0b11111 {
|
||||||
1..=23 => {
|
1..=23 => {
|
||||||
if access_unit.in_fu_a {
|
if access_unit.in_fu_a {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Non-fragmented NAL {:02x} while fragment in progress",
|
"Non-fragmented NAL {nal_header:02x} while fragment in progress"
|
||||||
nal_header
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let len = u32::try_from(data.len()).expect("data len < u16::MAX") + 1;
|
let len = u32::try_from(data.len()).expect("data len < u16::MAX") + 1;
|
||||||
@ -298,8 +296,7 @@ impl Depacketizer {
|
|||||||
}
|
}
|
||||||
25..=27 | 29 => {
|
25..=27 | 29 => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"unimplemented/unexpected interleaved mode NAL ({:02x})",
|
"unimplemented/unexpected interleaved mode NAL ({nal_header:02x})",
|
||||||
nal_header,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
28 => {
|
28 => {
|
||||||
@ -316,7 +313,7 @@ impl Depacketizer {
|
|||||||
.expect("NalHeader is valid");
|
.expect("NalHeader is valid");
|
||||||
data.advance(1);
|
data.advance(1);
|
||||||
if (start && end) || reserved {
|
if (start && end) || reserved {
|
||||||
return Err(format!("Invalid FU-A header {:02x}", fu_header));
|
return Err(format!("Invalid FU-A header {fu_header:02x}"));
|
||||||
}
|
}
|
||||||
if !end && mark {
|
if !end && mark {
|
||||||
return Err("FU-A pkt with MARK && !END".into());
|
return Err("FU-A pkt with MARK && !END".into());
|
||||||
@ -364,7 +361,7 @@ impl Depacketizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err(format!("bad nal header {:02x}", nal_header)),
|
_ => return Err(format!("bad nal header {nal_header:02x}")),
|
||||||
}
|
}
|
||||||
self.input_state = if mark {
|
self.input_state = if mark {
|
||||||
let last_nal_hdr = self.nals.last().unwrap().hdr;
|
let last_nal_hdr = self.nals.last().unwrap().hdr;
|
||||||
@ -677,12 +674,12 @@ impl InternalParameters {
|
|||||||
let sps = h264_reader::nal::sps::SeqParameterSet::from_bits(
|
let sps = h264_reader::nal::sps::SeqParameterSet::from_bits(
|
||||||
h264_reader::rbsp::BitReader::new(&*sps_rbsp),
|
h264_reader::rbsp::BitReader::new(&*sps_rbsp),
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Bad SPS: {:?}", e))?;
|
.map_err(|e| format!("Bad SPS: {e:?}"))?;
|
||||||
debug!("sps: {:#?}", &sps);
|
debug!("sps: {:#?}", &sps);
|
||||||
|
|
||||||
let pixel_dimensions = sps
|
let pixel_dimensions = sps
|
||||||
.pixel_dimensions()
|
.pixel_dimensions()
|
||||||
.map_err(|e| format!("SPS has invalid pixel dimensions: {:?}", e))?;
|
.map_err(|e| format!("SPS has invalid pixel dimensions: {e:?}"))?;
|
||||||
|
|
||||||
// Create the AVCDecoderConfiguration, ISO/IEC 14496-15 section 5.2.4.1.
|
// Create the AVCDecoderConfiguration, ISO/IEC 14496-15 section 5.2.4.1.
|
||||||
// The beginning of the AVCDecoderConfiguration takes a few values from
|
// The beginning of the AVCDecoderConfiguration takes a few values from
|
||||||
@ -860,7 +857,7 @@ impl Packetizer {
|
|||||||
let hdr = NalHeader::new(data[0]).map_err(|_| "F bit in NAL header".to_owned())?;
|
let hdr = NalHeader::new(data[0]).map_err(|_| "F bit in NAL header".to_owned())?;
|
||||||
if matches!(hdr.nal_unit_type(), UnitType::Unspecified(_)) {
|
if matches!(hdr.nal_unit_type(), UnitType::Unspecified(_)) {
|
||||||
// This can clash with fragmentation/aggregation NAL types.
|
// This can clash with fragmentation/aggregation NAL types.
|
||||||
return Err(format!("bad NAL header {:?}", hdr));
|
return Err(format!("bad NAL header {hdr:?}"));
|
||||||
}
|
}
|
||||||
if usize_len > max_payload_size {
|
if usize_len > max_payload_size {
|
||||||
// start a FU-A.
|
// start a FU-A.
|
||||||
@ -1156,7 +1153,7 @@ mod tests {
|
|||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&frame.data()[..],
|
frame.data(),
|
||||||
b"\x00\x00\x00\x06\x06plain\
|
b"\x00\x00\x00\x06\x06plain\
|
||||||
\x00\x00\x00\x09\x06stap-a 1\
|
\x00\x00\x00\x09\x06stap-a 1\
|
||||||
\x00\x00\x00\x09\x06stap-a 2\
|
\x00\x00\x00\x09\x06stap-a 2\
|
||||||
@ -1237,10 +1234,10 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let frame = match d.pull() {
|
let frame = match d.pull() {
|
||||||
Some(CodecItem::VideoFrame(frame)) => frame,
|
Some(CodecItem::VideoFrame(frame)) => frame,
|
||||||
o => panic!("unexpected pull result {:#?}", o),
|
o => panic!("unexpected pull result {o:#?}"),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&frame.data()[..],
|
frame.data(),
|
||||||
b"\x00\x00\x00\x0C\x67\x64\x00\x33\xac\x15\x14\xa0\xa0\x2f\xf9\x50\
|
b"\x00\x00\x00\x0C\x67\x64\x00\x33\xac\x15\x14\xa0\xa0\x2f\xf9\x50\
|
||||||
\x00\x00\x00\x04\x68\xee\x3c\xb0\
|
\x00\x00\x00\x04\x68\xee\x3c\xb0\
|
||||||
\x00\x00\x00\x06\x65slice"
|
\x00\x00\x00\x06\x65slice"
|
||||||
@ -1284,9 +1281,9 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let frame = match d.pull() {
|
let frame = match d.pull() {
|
||||||
Some(CodecItem::VideoFrame(frame)) => frame,
|
Some(CodecItem::VideoFrame(frame)) => frame,
|
||||||
o => panic!("unexpected pull result {:#?}", o),
|
o => panic!("unexpected pull result {o:#?}"),
|
||||||
};
|
};
|
||||||
assert_eq!(&frame.data()[..], b"\x00\x00\x00\x06\x01slice");
|
assert_eq!(frame.data(), b"\x00\x00\x00\x06\x01slice");
|
||||||
assert_eq!(frame.timestamp, ts1);
|
assert_eq!(frame.timestamp, ts1);
|
||||||
d.push(
|
d.push(
|
||||||
ReceivedPacketBuilder {
|
ReceivedPacketBuilder {
|
||||||
@ -1340,10 +1337,10 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let frame = match d.pull() {
|
let frame = match d.pull() {
|
||||||
Some(CodecItem::VideoFrame(frame)) => frame,
|
Some(CodecItem::VideoFrame(frame)) => frame,
|
||||||
o => panic!("unexpected pull result {:#?}", o),
|
o => panic!("unexpected pull result {o:#?}"),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&frame.data()[..],
|
frame.data(),
|
||||||
b"\x00\x00\x00\x0C\x67\x64\x00\x33\xac\x15\x14\xa0\xa0\x2f\xf9\x50\
|
b"\x00\x00\x00\x0C\x67\x64\x00\x33\xac\x15\x14\xa0\xa0\x2f\xf9\x50\
|
||||||
\x00\x00\x00\x04\x68\xee\x3c\xb0\
|
\x00\x00\x00\x04\x68\xee\x3c\xb0\
|
||||||
\x00\x00\x00\x06\x65slice"
|
\x00\x00\x00\x06\x65slice"
|
||||||
@ -1359,7 +1356,7 @@ mod tests {
|
|||||||
Some(crate::codec::ParametersRef::Video(v)) => {
|
Some(crate::codec::ParametersRef::Video(v)) => {
|
||||||
assert_eq!(v.pixel_dimensions(), (1920, 1080));
|
assert_eq!(v.pixel_dimensions(), (1920, 1080));
|
||||||
}
|
}
|
||||||
o => panic!("{:?}", o),
|
o => panic!("{o:?}"),
|
||||||
}
|
}
|
||||||
let timestamp = crate::Timestamp {
|
let timestamp = crate::Timestamp {
|
||||||
timestamp: 0,
|
timestamp: 0,
|
||||||
@ -1416,7 +1413,7 @@ mod tests {
|
|||||||
|
|
||||||
let frame = match d.pull() {
|
let frame = match d.pull() {
|
||||||
Some(CodecItem::VideoFrame(frame)) => frame,
|
Some(CodecItem::VideoFrame(frame)) => frame,
|
||||||
o => panic!("unexpected pull result {:#?}", o),
|
o => panic!("unexpected pull result {o:#?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// After pull, new_parameters and parameters() both reflect the change.
|
// After pull, new_parameters and parameters() both reflect the change.
|
||||||
|
@ -500,8 +500,7 @@ impl Depacketizer {
|
|||||||
encoding_name
|
encoding_name
|
||||||
);
|
);
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"no depacketizer for media/encoding_name {}/{}",
|
"no depacketizer for media/encoding_name {media}/{encoding_name}"
|
||||||
media, encoding_name
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -598,7 +597,7 @@ mod tests {
|
|||||||
std::mem::size_of::<MessageParameters>(),
|
std::mem::size_of::<MessageParameters>(),
|
||||||
),
|
),
|
||||||
] {
|
] {
|
||||||
println!("{:-40} {:4}", name, size);
|
println!("{name:-40} {size:4}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ impl<'a> PacketRef<'a> {
|
|||||||
}
|
}
|
||||||
let ver = buf[0] >> 6;
|
let ver = buf[0] >> 6;
|
||||||
if ver != 2 {
|
if ver != 2 {
|
||||||
return Err(format!("RTCP packets must be version 2; got {}", ver));
|
return Err(format!("RTCP packets must be version 2; got {ver}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// raw_len is "The length of this RTCP packet in 32-bit words minus one,
|
// raw_len is "The length of this RTCP packet in 32-bit words minus one,
|
||||||
@ -271,8 +271,7 @@ impl<'a> PacketRef<'a> {
|
|||||||
let padding_bytes = usize::from(this[len - 1]);
|
let padding_bytes = usize::from(this[len - 1]);
|
||||||
if padding_bytes == 0 || padding_bytes > len - COMMON_HEADER_LEN {
|
if padding_bytes == 0 || padding_bytes > len - COMMON_HEADER_LEN {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"RTCP packet of len {} states invalid {} padding bytes",
|
"RTCP packet of len {len} states invalid {padding_bytes} padding bytes"
|
||||||
len, padding_bytes
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -22,7 +22,7 @@ pub(crate) fn response(raw: &'static [u8]) -> rtsp_types::Response<Bytes> {
|
|||||||
let (msg, len) = rtsp_types::Message::parse(raw).unwrap();
|
let (msg, len) = rtsp_types::Message::parse(raw).unwrap();
|
||||||
assert_eq!(len, raw.len());
|
assert_eq!(len, raw.len());
|
||||||
match msg {
|
match msg {
|
||||||
rtsp_types::Message::Response(r) => r.map_body(|b| Bytes::from_static(b)),
|
rtsp_types::Message::Response(r) => r.map_body(Bytes::from_static),
|
||||||
_ => panic!("unexpected message type"),
|
_ => panic!("unexpected message type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user