rtc_rtp/codecs/vp8/
mod.rs1#[cfg(test)]
2mod vp8_test;
3
4use crate::packetizer::{Depacketizer, Payloader};
5use shared::error::{Error, Result};
6
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8
9pub const VP8_HEADER_SIZE: usize = 1;
10
11#[derive(Default, Debug, Copy, Clone)]
13pub struct Vp8Payloader {
14 pub enable_picture_id: bool,
15 picture_id: u16,
16}
17
18impl Payloader for Vp8Payloader {
19 fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> {
21 if payload.is_empty() || mtu == 0 {
22 return Ok(vec![]);
23 }
24
25 let using_header_size = if self.enable_picture_id {
46 if self.picture_id == 0 || self.picture_id < 128 {
47 VP8_HEADER_SIZE + 2
48 } else {
49 VP8_HEADER_SIZE + 3
50 }
51 } else {
52 VP8_HEADER_SIZE
53 };
54
55 let max_fragment_size = mtu as isize - using_header_size as isize;
56 let mut payload_data_remaining = payload.len() as isize;
57 let mut payload_data_index: usize = 0;
58 let mut payloads = vec![];
59
60 if std::cmp::min(max_fragment_size, payload_data_remaining) <= 0 {
62 return Ok(payloads);
63 }
64
65 let mut first = true;
66 while payload_data_remaining > 0 {
67 let current_fragment_size =
68 std::cmp::min(max_fragment_size, payload_data_remaining) as usize;
69 let mut out = BytesMut::with_capacity(using_header_size + current_fragment_size);
70 let mut buf = [0u8; 4];
71 if first {
72 buf[0] = 0x10;
73 first = false;
74 }
75
76 if self.enable_picture_id {
77 if using_header_size == VP8_HEADER_SIZE + 2 {
78 buf[0] |= 0x80;
79 buf[1] |= 0x80;
80 buf[2] |= (self.picture_id & 0x7F) as u8;
81 } else if using_header_size == VP8_HEADER_SIZE + 3 {
82 buf[0] |= 0x80;
83 buf[1] |= 0x80;
84 buf[2] |= 0x80 | ((self.picture_id >> 8) & 0x7F) as u8;
85 buf[3] |= (self.picture_id & 0xFF) as u8;
86 }
87 }
88
89 out.put(&buf[..using_header_size]);
90
91 out.put(
92 &*payload.slice(payload_data_index..payload_data_index + current_fragment_size),
93 );
94 payloads.push(out.freeze());
95
96 payload_data_remaining -= current_fragment_size as isize;
97 payload_data_index += current_fragment_size;
98 }
99
100 self.picture_id += 1;
101 self.picture_id &= 0x7FFF;
102
103 Ok(payloads)
104 }
105
106 fn clone_to(&self) -> Box<dyn Payloader> {
107 Box::new(*self)
108 }
109}
110
111#[derive(PartialEq, Eq, Debug, Default, Clone)]
113pub struct Vp8Packet {
114 pub x: u8,
117 pub n: u8,
119 pub s: u8,
121 pub pid: u8,
123
124 pub i: u8,
127 pub l: u8,
129 pub t: u8,
131 pub k: u8,
133
134 pub picture_id: u16,
137 pub tl0_pic_idx: u8,
139 pub tid: u8,
141 pub y: u8,
143 pub key_idx: u8,
145}
146
147impl Depacketizer for Vp8Packet {
148 fn depacketize(&mut self, packet: &Bytes) -> Result<Bytes> {
150 let payload_len = packet.len();
151 if payload_len < 4 {
152 return Err(Error::ErrShortPacket);
153 }
154 let reader = &mut packet.clone();
170 let mut payload_index = 0;
171
172 let mut b = reader.get_u8();
173 payload_index += 1;
174
175 self.x = (b & 0x80) >> 7;
176 self.n = (b & 0x20) >> 5;
177 self.s = (b & 0x10) >> 4;
178 self.pid = b & 0x07;
179
180 if self.x == 1 {
181 b = reader.get_u8();
182 payload_index += 1;
183 self.i = (b & 0x80) >> 7;
184 self.l = (b & 0x40) >> 6;
185 self.t = (b & 0x20) >> 5;
186 self.k = (b & 0x10) >> 4;
187 }
188
189 if self.i == 1 {
190 b = reader.get_u8();
191 payload_index += 1;
192 if b & 0x80 > 0 {
194 self.picture_id = (((b & 0x7f) as u16) << 8) | (reader.get_u8() as u16);
196 payload_index += 1;
197 } else {
198 self.picture_id = b as u16;
199 }
200 }
201
202 if payload_index >= payload_len {
203 return Err(Error::ErrShortPacket);
204 }
205
206 if self.l == 1 {
207 self.tl0_pic_idx = reader.get_u8();
208 payload_index += 1;
209 }
210
211 if payload_index >= payload_len {
212 return Err(Error::ErrShortPacket);
213 }
214
215 if self.t == 1 || self.k == 1 {
216 let b = reader.get_u8();
217 if self.t == 1 {
218 self.tid = b >> 6;
219 self.y = (b >> 5) & 0x1;
220 }
221 if self.k == 1 {
222 self.key_idx = b & 0x1F;
223 }
224 payload_index += 1;
225 }
226
227 if payload_index >= packet.len() {
228 return Err(Error::ErrShortPacket);
229 }
230
231 Ok(packet.slice(payload_index..))
232 }
233
234 fn is_partition_head(&self, payload: &Bytes) -> bool {
236 if payload.is_empty() {
237 false
238 } else {
239 (payload[0] & 0x10) != 0
240 }
241 }
242
243 fn is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool {
244 marker
245 }
246}