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