rtc_rtp/extension/audio_level_extension/mod.rs
1#[cfg(test)]
2mod audio_level_extension_test;
3
4use serde::{Deserialize, Serialize};
5use shared::{
6 error::{Error, Result},
7 marshal::{Marshal, MarshalSize, Unmarshal},
8};
9
10use bytes::{Buf, BufMut};
11
12// AUDIO_LEVEL_EXTENSION_SIZE One byte header size
13/// The extension's encoded size in bytes.
14pub const AUDIO_LEVEL_EXTENSION_SIZE: usize = 1;
15
16/// AudioLevelExtension is a extension payload format described in
17/// <https://tools.ietf.org/html/rfc6464>
18///
19/// Implementation based on:
20/// <https://chromium.googlesource.com/external/webrtc/+/e2a017725570ead5946a4ca8235af27470ca0df9/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.cc#49>
21///
22/// One byte format:
23/// 0 1
24/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
25/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26/// | ID | len=0 |V| level |
27/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28///
29/// Two byte format:
30/// 0 1 2 3
31/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
32/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33/// | ID | len=1 |V| level | 0 (pad) |
34/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35///
36/// ## Specifications
37///
38/// * [RFC 6464]
39///
40/// [RFC 6464]: https://tools.ietf.org/html/rfc6464
41#[derive(PartialEq, Eq, Debug, Default, Copy, Clone, Serialize, Deserialize)]
42pub struct AudioLevelExtension {
43 /// Loudness in −dBov, from 0 (loudest) to 127 (silence).
44 pub level: u8,
45 /// Whether the sender detected voice activity in this packet.
46 pub voice: bool,
47}
48
49impl Unmarshal for AudioLevelExtension {
50 /// Unmarshal parses the passed byte slice and stores the result in the members
51 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
52 where
53 Self: Sized,
54 B: Buf,
55 {
56 if raw_packet.remaining() < AUDIO_LEVEL_EXTENSION_SIZE {
57 return Err(Error::ErrBufferTooSmall);
58 }
59
60 let b = raw_packet.get_u8();
61
62 Ok(AudioLevelExtension {
63 level: b & 0x7F,
64 voice: (b & 0x80) != 0,
65 })
66 }
67}
68
69impl MarshalSize for AudioLevelExtension {
70 /// MarshalSize returns the size of the AudioLevelExtension once marshaled.
71 fn marshal_size(&self) -> usize {
72 AUDIO_LEVEL_EXTENSION_SIZE
73 }
74}
75
76impl Marshal for AudioLevelExtension {
77 /// MarshalTo serializes the members to buffer
78 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
79 if buf.remaining_mut() < AUDIO_LEVEL_EXTENSION_SIZE {
80 return Err(Error::ErrBufferTooSmall);
81 }
82 if self.level > 127 {
83 return Err(Error::AudioLevelOverflow);
84 }
85 let voice = if self.voice { 0x80u8 } else { 0u8 };
86
87 buf.put_u8(voice | self.level);
88
89 Ok(AUDIO_LEVEL_EXTENSION_SIZE)
90 }
91}