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}