Skip to content
File

Blob: firmware/vendor/str0m/src/packet/mod.rs

rust518 lines
1#![allow(clippy::type_complexity)]
2 
3use std::fmt;
4use std::panic::UnwindSafe;
5 
6use crate::format::Codec;
7use crate::sdp::MediaType;
8 
9use crate::rtp::vla::encode_leb_u63;
10 
11mod av1;
12pub use av1::Av1CodecExtra;
13pub use av1::detect_av1_keyframe;
14use av1::{Av1Depacketizer, Av1Packetizer};
15 
16mod g7xx;
17use g7xx::{G711Depacketizer, G711Packetizer, G722Packetizer};
18 
19mod h264;
20pub use h264::H264CodecExtra;
21pub use h264::detect_h264_keyframe;
22pub use h264::{H264Depacketizer, H264Packetizer};
23 
24mod h264_profile;
25pub(crate) use h264_profile::H264ProfileLevel;
26 
27mod h265;
28pub use h265::H265CodecExtra;
29use h265::H265Depacketizer;
30pub use h265::H265Packetizer;
31pub use h265::detect_h265_keyframe;
32 
33mod h265_profile;
34pub use h265_profile::{H265Level, H265Profile, H265ProfileTierLevel, H265Tier};
35 
36mod h266;
37pub use h266::H266CodecExtra;
38use h266::H266Depacketizer;
39pub use h266::H266Packetizer;
40pub use h266::detect_h266_keyframe;
41 
42mod h266_profile;
43pub use h266_profile::{H266Level, H266Profile, H266ProfileTierLevel, H266Tier};
44 
45mod opus;
46pub use opus::{OpusDepacketizer, OpusPacketizer};
47 
48mod vp8;
49pub use vp8::Vp8CodecExtra;
50pub use vp8::Vp8Descriptor;
51pub use vp8::Vp8DescriptorError;
52pub use vp8::Vp8Patch;
53pub use vp8::Vp8PatchBuilder;
54pub use vp8::Vp8PatchError;
55pub use vp8::detect_vp8_keyframe;
56pub use vp8::{Vp8Depacketizer, Vp8Packetizer};
57 
58mod vp9;
59pub use vp9::Vp9CodecExtra;
60pub use vp9::Vp9PacketizerMode;
61pub use vp9::detect_vp9_keyframe;
62use vp9::{Vp9Depacketizer, Vp9Packetizer};
63 
64mod null;
65use null::{NullDepacketizer, NullPacketizer};
66 
67mod comfort_noise;
68use comfort_noise::{ComfortNoiseDepacketizer, ComfortNoisePacketizer};
69 
70mod buffer_rx;
71pub(crate) use buffer_rx::{DepacketizingBuffer, RtpMeta};
72 
73mod contiguity;
74mod contiguity_vp8;
75mod contiguity_vp9;
76mod error;
77 
78mod payload;
79pub(crate) use payload::Payloader;
80 
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
82/// Types of media.
83pub enum MediaKind {
84 /// Audio media.
85 Audio,
86 /// Video media.
87 Video,
88}
89 
90#[cfg(feature = "drv")]
91crate::drv_identity_copy!(MediaKind);
92 
93impl MediaKind {
94 /// Tests if this is `MediaKind::Audio`
95 pub fn is_audio(&self) -> bool {
96 *self == MediaKind::Audio
97 }
98 
99 /// Tests if this is `MediaKind::Video`
100 pub fn is_video(&self) -> bool {
101 *self == MediaKind::Video
102 }
103}
104 
105/// Packetizes some bytes for use as RTP packet.
106///
107/// ## Unversioned API surface
108///
109/// This trait is not currently versioned according to semver rules.
110/// Breaking changes may be made in minor or patch releases.
111pub trait Packetizer: fmt::Debug {
112 /// Chunk the data up into RTP packets.
113 fn packetize(&mut self, mtu: usize, b: &[u8]) -> Result<Vec<Vec<u8>>, PacketError>;
114 
115 /// Tell if this is the last packet of a frame.
116 fn is_marker(&mut self, data: &[u8], previous: Option<&[u8]>, last: bool) -> bool;
117}
118 
119/// Codec specific information
120///
121/// Contains additional codec specific information which are deemed useful for
122/// managing and repackaging the frame
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124#[non_exhaustive]
125pub enum CodecExtra {
126 /// No extra information available
127 None,
128 /// Codec extra parameters for VP8.
129 Vp8(Vp8CodecExtra),
130 /// Codec extra parameters for VP9.
131 Vp9(Vp9CodecExtra),
132 /// Codec extra parameters for H264.
133 H264(H264CodecExtra),
134 /// Codec extra parameters for AV1,
135 Av1(Av1CodecExtra),
136 /// Codec extra parameters for H265.
137 H265(H265CodecExtra),
138 /// Codec extra parameters for H266 (VVC). Prototype.
139 H266(H266CodecExtra),
140}
141 
142/// Depacketizes an RTP payload.
143///
144/// Removes any RTP specific data from the payload.
145///
146/// ## Unversioned API surface
147///
148/// This trait is not currently versioned according to semver rules.
149/// Breaking changes may be made in minor or patch releases.
150pub trait Depacketizer: fmt::Debug {
151 /// Provide a size hint for the `out: &mut Vec<u8>` parameter in [`Depacketizer::depacketize`].
152 /// The [`packets_size`] parameter is the sum of the size of all packets that will be processed in
153 /// subsequent calls to [`Depacketizer::depacketize`].
154 /// This is used to allocate the vector with upfront capacity.
155 /// Return [`None`] if it cannot be determined.
156 fn out_size_hint(&self, packets_size: usize) -> Option<usize>;
157 
158 /// Unpack the RTP packet into a provided `Vec<u8>`.
159 fn depacketize(
160 &mut self,
161 packet: &[u8],
162 out: &mut Vec<u8>,
163 codec_extra: &mut CodecExtra,
164 ) -> Result<(), PacketError>;
165 
166 /// Checks if the packet is at the beginning of a partition.
167 ///
168 /// Returns false if the result could not be determined.
169 fn is_partition_head(&self, packet: &[u8]) -> bool;
170 
171 /// Checks if the packet is at the end of a partition.
172 ///
173 /// Returns false if the result could not be determined.
174 fn is_partition_tail(&self, marker: bool, packet: &[u8]) -> bool;
175}
176 
177pub use error::PacketError;
178 
179/// Helper to replace Bytes. Provides get_u8 and get_u16 over some buffer of bytes.
180pub(crate) trait BitRead {
181 fn remaining_bits(&self) -> usize;
182 fn remaining_bytes(&self) -> usize;
183 fn byte_offset(&self) -> usize;
184 fn get_u8(&mut self) -> Option<u8>;
185 fn get_u16(&mut self) -> Option<u16>;
186 fn get_remaining(&mut self) -> &[u8];
187 fn get_bytes(&mut self, count: usize) -> Option<&[u8]>;
188 fn get_leb128(&mut self) -> Option<usize>;
189 fn skip_bytes(&mut self, count: usize);
190}
191 
192impl BitRead for (&[u8], usize) {
193 #[inline(always)]
194 fn remaining_bits(&self) -> usize {
195 (self.0.len() * 8).saturating_sub(self.1)
196 }
197 
198 #[inline(always)]
199 fn remaining_bytes(&self) -> usize {
200 self.remaining_bits() / 8
201 }
202 
203 #[inline(always)]
204 fn byte_offset(&self) -> usize {
205 self.1 / 8
206 }
207 
208 #[inline(always)]
209 fn get_u8(&mut self) -> Option<u8> {
210 if self.remaining_bits() < 8 {
211 return None;
212 }
213 
214 let offs = self.1 / 8;
215 let shift = (self.1 % 8) as u32;
216 self.1 += 8;
217 
218 let mut n = self.0[offs];
219 
220 if shift > 0 {
221 n <<= shift;
222 n |= self.0[offs + 1] >> (8 - shift)
223 }
224 
225 Some(n)
226 }
227 
228 fn get_u16(&mut self) -> Option<u16> {
229 if self.remaining_bits() < 16 {
230 return None;
231 }
232 Some(u16::from_be_bytes([self.get_u8()?, self.get_u8()?]))
233 }
234 
235 fn get_remaining(&mut self) -> &[u8] {
236 let offset = self.1 / 8;
237 self.1 = self.0.len() * 8;
238 &self.0[offset..]
239 }
240 
241 fn get_bytes(&mut self, count: usize) -> Option<&[u8]> {
242 let count_bits = count.saturating_mul(8);
243 if self.remaining_bits() < count_bits {
244 return None;
245 }
246 let offset = self.1 / 8;
247 self.1 += count_bits;
248 Some(&self.0[offset..offset + count])
249 }
250 
251 fn get_leb128(&mut self) -> Option<usize> {
252 let mut temp_value: usize = 0;
253 
254 for i in (0..64).step_by(7) {
255 if self.remaining_bits() < 8 {
256 return None;
257 }
258 let byte = self.get_u8().unwrap();
259 temp_value |= ((byte & 0x7f) as usize) << i;
260 
261 if byte < 0x80 {
262 return Some(temp_value);
263 }
264 }
265 
266 None
267 }
268 
269 fn skip_bytes(&mut self, count: usize) {
270 let bits = count.saturating_mul(8);
271 if self.remaining_bits() < bits {
272 return;
273 }
274 
275 self.1 += bits;
276 }
277}
278 
279#[derive(Debug)]
280pub(crate) enum CodecPacketizer {
281 #[allow(unused)]
282 G711(G711Packetizer),
283 #[allow(unused)]
284 G722(G722Packetizer),
285 H264(H264Packetizer),
286 H265(H265Packetizer),
287 H266(H266Packetizer),
288 Opus(OpusPacketizer),
289 ComfortNoise(ComfortNoisePacketizer),
290 Vp8(Vp8Packetizer),
291 Vp9(Vp9Packetizer),
292 Av1(Av1Packetizer),
293 Null(NullPacketizer),
294 #[allow(unused)]
295 Boxed(Box<dyn Packetizer + Send + Sync + UnwindSafe>),
296}
297 
298#[derive(Debug)]
299pub(crate) enum CodecDepacketizer {
300 G711(G711Depacketizer),
301 H264(H264Depacketizer),
302 H265(H265Depacketizer),
303 H266(H266Depacketizer),
304 Opus(OpusDepacketizer),
305 ComfortNoise(ComfortNoiseDepacketizer),
306 Vp8(Vp8Depacketizer),
307 Vp9(Vp9Depacketizer),
308 Av1(Av1Depacketizer),
309 Null(NullDepacketizer),
310 #[allow(unused)]
311 Boxed(Box<dyn Depacketizer + Send + Sync + UnwindSafe>),
312}
313 
314impl CodecPacketizer {
315 pub(crate) fn new(codec: Codec, vp9_mode: Vp9PacketizerMode) -> Self {
316 match codec {
317 Codec::Opus => CodecPacketizer::Opus(OpusPacketizer),
318 Codec::PCMU => CodecPacketizer::G711(G711Packetizer::default()),
319 Codec::PCMA => CodecPacketizer::G711(G711Packetizer::default()),
320 Codec::G722 => CodecPacketizer::G722(G722Packetizer::default()),
321 Codec::CN => CodecPacketizer::ComfortNoise(ComfortNoisePacketizer),
322 Codec::H264 => CodecPacketizer::H264(H264Packetizer::default()),
323 Codec::H265 => CodecPacketizer::H265(H265Packetizer::default()),
324 Codec::H266 => CodecPacketizer::H266(H266Packetizer::default()),
325 Codec::Vp8 => CodecPacketizer::Vp8(Vp8Packetizer::default()),
326 Codec::Vp9 => CodecPacketizer::Vp9(Vp9Packetizer::with_mode(vp9_mode)),
327 Codec::Av1 => CodecPacketizer::Av1(Av1Packetizer::default()),
328 Codec::Null => CodecPacketizer::Null(NullPacketizer),
329 Codec::Rtx => panic!("Cant instantiate packetizer for RTX codec"),
330 Codec::Unknown => panic!("Cant instantiate packetizer for unknown codec"),
331 }
332 }
333}
334 
335impl From<Codec> for CodecPacketizer {
336 fn from(c: Codec) -> Self {
337 CodecPacketizer::new(c, Vp9PacketizerMode::default())
338 }
339}
340 
341impl From<Codec> for CodecDepacketizer {
342 fn from(c: Codec) -> Self {
343 match c {
344 Codec::Opus => CodecDepacketizer::Opus(OpusDepacketizer),
345 Codec::PCMU => CodecDepacketizer::G711(G711Depacketizer),
346 Codec::PCMA => CodecDepacketizer::G711(G711Depacketizer),
347 Codec::G722 => CodecDepacketizer::G711(G711Depacketizer),
348 Codec::CN => CodecDepacketizer::ComfortNoise(ComfortNoiseDepacketizer),
349 Codec::H264 => CodecDepacketizer::H264(H264Depacketizer::default()),
350 Codec::H265 => CodecDepacketizer::H265(H265Depacketizer::default()),
351 Codec::H266 => CodecDepacketizer::H266(H266Depacketizer::default()),
352 Codec::Vp8 => CodecDepacketizer::Vp8(Vp8Depacketizer::default()),
353 Codec::Vp9 => CodecDepacketizer::Vp9(Vp9Depacketizer::default()),
354 Codec::Av1 => CodecDepacketizer::Av1(Av1Depacketizer::default()),
355 Codec::Null => CodecDepacketizer::Null(NullDepacketizer),
356 Codec::Rtx => panic!("Cant instantiate depacketizer for RTX codec"),
357 Codec::Unknown => panic!("Cant instantiate depacketizer for unknown codec"),
358 }
359 }
360}
361 
362impl Packetizer for CodecPacketizer {
363 fn packetize(&mut self, mtu: usize, b: &[u8]) -> Result<Vec<Vec<u8>>, PacketError> {
364 use CodecPacketizer::*;
365 match self {
366 G711(v) => v.packetize(mtu, b),
367 G722(v) => v.packetize(mtu, b),
368 H264(v) => v.packetize(mtu, b),
369 H265(v) => v.packetize(mtu, b),
370 H266(v) => v.packetize(mtu, b),
371 Opus(v) => v.packetize(mtu, b),
372 ComfortNoise(v) => v.packetize(mtu, b),
373 Vp8(v) => v.packetize(mtu, b),
374 Vp9(v) => v.packetize(mtu, b),
375 Av1(v) => v.packetize(mtu, b),
376 Null(v) => v.packetize(mtu, b),
377 Boxed(v) => v.packetize(mtu, b),
378 }
379 }
380 
381 fn is_marker(&mut self, data: &[u8], previous: Option<&[u8]>, last: bool) -> bool {
382 match self {
383 CodecPacketizer::G711(v) => v.is_marker(data, previous, last),
384 CodecPacketizer::G722(v) => v.is_marker(data, previous, last),
385 CodecPacketizer::Opus(v) => v.is_marker(data, previous, last),
386 CodecPacketizer::ComfortNoise(v) => v.is_marker(data, previous, last),
387 CodecPacketizer::H264(v) => v.is_marker(data, previous, last),
388 CodecPacketizer::H265(v) => v.is_marker(data, previous, last),
389 CodecPacketizer::H266(v) => v.is_marker(data, previous, last),
390 CodecPacketizer::Vp8(v) => v.is_marker(data, previous, last),
391 CodecPacketizer::Vp9(v) => v.is_marker(data, previous, last),
392 CodecPacketizer::Av1(v) => v.is_marker(data, previous, last),
393 CodecPacketizer::Null(v) => v.is_marker(data, previous, last),
394 CodecPacketizer::Boxed(v) => v.is_marker(data, previous, last),
395 }
396 }
397}
398 
399impl Depacketizer for CodecDepacketizer {
400 fn out_size_hint(&self, packets_size: usize) -> Option<usize> {
401 use CodecDepacketizer::*;
402 match self {
403 H264(v) => v.out_size_hint(packets_size),
404 H265(v) => v.out_size_hint(packets_size),
405 H266(v) => v.out_size_hint(packets_size),
406 Opus(v) => v.out_size_hint(packets_size),
407 ComfortNoise(v) => v.out_size_hint(packets_size),
408 G711(v) => v.out_size_hint(packets_size),
409 Vp8(v) => v.out_size_hint(packets_size),
410 Vp9(v) => v.out_size_hint(packets_size),
411 Av1(v) => v.out_size_hint(packets_size),
412 Null(v) => v.out_size_hint(packets_size),
413 Boxed(v) => v.out_size_hint(packets_size),
414 }
415 }
416 
417 fn depacketize(
418 &mut self,
419 packet: &[u8],
420 out: &mut Vec<u8>,
421 extra: &mut CodecExtra,
422 ) -> Result<(), PacketError> {
423 use CodecDepacketizer::*;
424 match self {
425 H264(v) => v.depacketize(packet, out, extra),
426 H265(v) => v.depacketize(packet, out, extra),
427 H266(v) => v.depacketize(packet, out, extra),
428 Opus(v) => v.depacketize(packet, out, extra),
429 ComfortNoise(v) => v.depacketize(packet, out, extra),
430 G711(v) => v.depacketize(packet, out, extra),
431 Vp8(v) => v.depacketize(packet, out, extra),
432 Vp9(v) => v.depacketize(packet, out, extra),
433 Av1(v) => v.depacketize(packet, out, extra),
434 Null(v) => v.depacketize(packet, out, extra),
435 Boxed(v) => v.depacketize(packet, out, extra),
436 }
437 }
438 
439 fn is_partition_head(&self, packet: &[u8]) -> bool {
440 use CodecDepacketizer::*;
441 match self {
442 H264(v) => v.is_partition_head(packet),
443 H265(v) => v.is_partition_head(packet),
444 H266(v) => v.is_partition_head(packet),
445 Opus(v) => v.is_partition_head(packet),
446 ComfortNoise(v) => v.is_partition_head(packet),
447 G711(v) => v.is_partition_head(packet),
448 Vp8(v) => v.is_partition_head(packet),
449 Vp9(v) => v.is_partition_head(packet),
450 Av1(v) => v.is_partition_head(packet),
451 Null(v) => v.is_partition_head(packet),
452 Boxed(v) => v.is_partition_head(packet),
453 }
454 }
455 
456 fn is_partition_tail(&self, marker: bool, packet: &[u8]) -> bool {
457 use CodecDepacketizer::*;
458 match self {
459 H264(v) => v.is_partition_tail(marker, packet),
460 H265(v) => v.is_partition_tail(marker, packet),
461 H266(v) => v.is_partition_tail(marker, packet),
462 Opus(v) => v.is_partition_tail(marker, packet),
463 ComfortNoise(v) => v.is_partition_tail(marker, packet),
464 G711(v) => v.is_partition_tail(marker, packet),
465 Vp8(v) => v.is_partition_tail(marker, packet),
466 Vp9(v) => v.is_partition_tail(marker, packet),
467 Av1(v) => v.is_partition_tail(marker, packet),
468 Null(v) => v.is_partition_tail(marker, packet),
469 Boxed(v) => v.is_partition_tail(marker, packet),
470 }
471 }
472}
473 
474impl From<MediaType> for MediaKind {
475 fn from(v: MediaType) -> Self {
476 match v {
477 MediaType::Audio => MediaKind::Audio,
478 MediaType::Video => MediaKind::Video,
479 _ => panic!("Not MediaType::Audio or Video"),
480 }
481 }
482}
483 
484impl fmt::Display for MediaKind {
485 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486 match self {
487 MediaKind::Audio => write!(f, "audio"),
488 MediaKind::Video => write!(f, "video"),
489 }
490 }
491}
492 
493#[cfg(test)]
494mod test {
495 use super::*;
496 
497 #[test]
498 fn comfort_noise_packetizer_preserves_payload_and_clears_marker() {
499 let payload = [42, 128, 64];
500 let mut packetizer = CodecPacketizer::from(Codec::CN);
501 
502 assert_eq!(
503 packetizer.packetize(1200, &payload).unwrap(),
504 vec![payload.to_vec()]
505 );
506 assert!(!packetizer.is_marker(&payload, None, true));
507 
508 let mut depacketizer = CodecDepacketizer::from(Codec::CN);
509 let mut output = Vec::new();
510 depacketizer
511 .depacketize(&payload, &mut output, &mut CodecExtra::None)
512 .unwrap();
513 assert_eq!(output, payload);
514 assert!(depacketizer.is_partition_head(&payload));
515 assert!(depacketizer.is_partition_tail(false, &payload));
516 }
517}