Skip to main content

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}