1#[cfg(test)]
2mod vp9_test;
3
4use crate::packetizer::{Depacketizer, Payloader};
5use shared::error::{Error, Result};
6
7use bytes::{Buf, BufMut, Bytes, BytesMut};
8use std::fmt;
9use std::sync::Arc;
10
11const VP9HEADER_SIZE: usize = 3;
13const MAX_SPATIAL_LAYERS: u8 = 5;
14const MAX_VP9REF_PICS: usize = 3;
15
16pub type InitialPictureIDFn = Arc<dyn (Fn() -> u16) + Send + Sync>;
18
19#[derive(Default, Clone)]
21pub struct Vp9Payloader {
22 picture_id: u16,
23 initialized: bool,
24
25 pub initial_picture_id_fn: Option<InitialPictureIDFn>,
27}
28
29impl fmt::Debug for Vp9Payloader {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("Vp9Payloader")
32 .field("picture_id", &self.picture_id)
33 .field("initialized", &self.initialized)
34 .finish()
35 }
36}
37
38impl Payloader for Vp9Payloader {
39 fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> {
41 if payload.is_empty() || mtu == 0 {
80 return Ok(vec![]);
81 }
82
83 if !self.initialized {
84 if self.initial_picture_id_fn.is_none() {
85 self.initial_picture_id_fn =
86 Some(Arc::new(|| -> u16 { rand::random::<u16>() & 0x7FFF }));
87 }
88 self.picture_id = if let Some(f) = &self.initial_picture_id_fn {
89 f()
90 } else {
91 0
92 };
93 self.initialized = true;
94 }
95
96 let max_fragment_size = mtu as isize - VP9HEADER_SIZE as isize;
97 let mut payloads = vec![];
98 let mut payload_data_remaining = payload.len();
99 let mut payload_data_index = 0;
100
101 if std::cmp::min(max_fragment_size, payload_data_remaining as isize) <= 0 {
102 return Ok(vec![]);
103 }
104
105 while payload_data_remaining > 0 {
106 let current_fragment_size =
107 std::cmp::min(max_fragment_size as usize, payload_data_remaining);
108 let mut out = BytesMut::with_capacity(VP9HEADER_SIZE + current_fragment_size);
109 let mut buf = [0u8; VP9HEADER_SIZE];
110 buf[0] = 0x90; if payload_data_index == 0 {
112 buf[0] |= 0x08; }
114 if payload_data_remaining == current_fragment_size {
115 buf[0] |= 0x04; }
117 buf[1] = (self.picture_id >> 8) as u8 | 0x80;
118 buf[2] = (self.picture_id & 0xFF) as u8;
119
120 out.put(&buf[..]);
121
122 out.put(
123 &*payload.slice(payload_data_index..payload_data_index + current_fragment_size),
124 );
125
126 payloads.push(out.freeze());
127
128 payload_data_remaining -= current_fragment_size;
129 payload_data_index += current_fragment_size;
130 }
131
132 self.picture_id += 1;
133 self.picture_id &= 0x7FFF;
134
135 Ok(payloads)
136 }
137
138 fn clone_to(&self) -> Box<dyn Payloader> {
139 Box::new(self.clone())
140 }
141}
142
143#[derive(PartialEq, Eq, Debug, Default, Clone)]
145pub struct Vp9Packet {
146 pub i: bool,
148 pub p: bool,
150 pub l: bool,
152 pub f: bool,
154 pub b: bool,
156 pub e: bool,
158 pub v: bool,
160 pub z: bool,
162
163 pub picture_id: u16,
166
167 pub tid: u8,
170 pub u: bool,
172 pub sid: u8,
174 pub d: bool,
176
177 pub pdiff: Vec<u8>,
180 pub tl0picidx: u8,
182
183 pub ns: u8,
186 pub y: bool,
188 pub g: bool,
190 pub ng: u8,
192 pub width: Vec<u16>,
194 pub height: Vec<u16>,
196 pub pgtid: Vec<u8>,
198 pub pgu: Vec<bool>,
200 pub pgpdiff: Vec<Vec<u8>>,
202}
203
204impl Depacketizer for Vp9Packet {
205 fn depacketize(&mut self, packet: &Bytes) -> Result<Bytes> {
207 if packet.is_empty() {
208 return Err(Error::ErrShortPacket);
209 }
210
211 let reader = &mut packet.clone();
212 let b = reader.get_u8();
213
214 self.i = (b & 0x80) != 0;
215 self.p = (b & 0x40) != 0;
216 self.l = (b & 0x20) != 0;
217 self.f = (b & 0x10) != 0;
218 self.b = (b & 0x08) != 0;
219 self.e = (b & 0x04) != 0;
220 self.v = (b & 0x02) != 0;
221 self.z = (b & 0x01) != 0;
222
223 let mut payload_index = 1;
224
225 if self.i {
226 payload_index = self.parse_picture_id(reader, payload_index)?;
227 }
228
229 if self.l {
230 payload_index = self.parse_layer_info(reader, payload_index)?;
231 }
232
233 if self.f && self.p {
234 payload_index = self.parse_ref_indices(reader, payload_index)?;
235 }
236
237 if self.v {
238 payload_index = self.parse_ssdata(reader, payload_index)?;
239 }
240
241 Ok(packet.slice(payload_index..))
242 }
243
244 fn is_partition_head(&self, payload: &Bytes) -> bool {
246 if payload.is_empty() {
247 false
248 } else {
249 (payload[0] & 0x08) != 0
250 }
251 }
252
253 fn is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool {
254 marker
255 }
256}
257
258impl Vp9Packet {
259 fn parse_picture_id(
268 &mut self,
269 reader: &mut dyn Buf,
270 mut payload_index: usize,
271 ) -> Result<usize> {
272 if reader.remaining() == 0 {
273 return Err(Error::ErrShortPacket);
274 }
275 let b = reader.get_u8();
276 payload_index += 1;
277 if (b & 0x80) != 0 {
279 if reader.remaining() == 0 {
280 return Err(Error::ErrShortPacket);
281 }
282 self.picture_id = (((b & 0x7f) as u16) << 8) | (reader.get_u8() as u16);
284 payload_index += 1;
285 } else {
286 self.picture_id = (b & 0x7F) as u16;
287 }
288
289 Ok(payload_index)
290 }
291
292 fn parse_layer_info(
293 &mut self,
294 reader: &mut dyn Buf,
295 mut payload_index: usize,
296 ) -> Result<usize> {
297 payload_index = self.parse_layer_info_common(reader, payload_index)?;
298
299 if self.f {
300 Ok(payload_index)
301 } else {
302 self.parse_layer_info_non_flexible_mode(reader, payload_index)
303 }
304 }
305
306 fn parse_layer_info_common(
313 &mut self,
314 reader: &mut dyn Buf,
315 mut payload_index: usize,
316 ) -> Result<usize> {
317 if reader.remaining() == 0 {
318 return Err(Error::ErrShortPacket);
319 }
320 let b = reader.get_u8();
321 payload_index += 1;
322
323 self.tid = b >> 5;
324 self.u = b & 0x10 != 0;
325 self.sid = (b >> 1) & 0x7;
326 self.d = b & 0x01 != 0;
327
328 if self.sid >= MAX_SPATIAL_LAYERS {
329 Err(Error::ErrTooManySpatialLayers)
330 } else {
331 Ok(payload_index)
332 }
333 }
334
335 fn parse_layer_info_non_flexible_mode(
344 &mut self,
345 reader: &mut dyn Buf,
346 mut payload_index: usize,
347 ) -> Result<usize> {
348 if reader.remaining() == 0 {
349 return Err(Error::ErrShortPacket);
350 }
351 self.tl0picidx = reader.get_u8();
352 payload_index += 1;
353 Ok(payload_index)
354 }
355
356 fn parse_ref_indices(
364 &mut self,
365 reader: &mut dyn Buf,
366 mut payload_index: usize,
367 ) -> Result<usize> {
368 let mut b = 1u8;
369 while (b & 0x1) != 0 {
370 if reader.remaining() == 0 {
371 return Err(Error::ErrShortPacket);
372 }
373 b = reader.get_u8();
374 payload_index += 1;
375
376 self.pdiff.push(b >> 1);
377 if self.pdiff.len() >= MAX_VP9REF_PICS {
378 return Err(Error::ErrTooManyPDiff);
379 }
380 }
381
382 Ok(payload_index)
383 }
384
385 fn parse_ssdata(&mut self, reader: &mut dyn Buf, mut payload_index: usize) -> Result<usize> {
406 if reader.remaining() == 0 {
407 return Err(Error::ErrShortPacket);
408 }
409
410 let b = reader.get_u8();
411 payload_index += 1;
412
413 self.ns = b >> 5;
414 self.y = b & 0x10 != 0;
415 self.g = (b >> 1) & 0x7 != 0;
416
417 let ns = (self.ns + 1) as usize;
418 self.ng = 0;
419
420 if self.y {
421 if reader.remaining() < 4 * ns {
422 return Err(Error::ErrShortPacket);
423 }
424
425 self.width = vec![0u16; ns];
426 self.height = vec![0u16; ns];
427 for i in 0..ns {
428 self.width[i] = reader.get_u16();
429 self.height[i] = reader.get_u16();
430 }
431 payload_index += 4 * ns;
432 }
433
434 if self.g {
435 if reader.remaining() == 0 {
436 return Err(Error::ErrShortPacket);
437 }
438
439 self.ng = reader.get_u8();
440 payload_index += 1;
441 }
442
443 for i in 0..self.ng as usize {
444 if reader.remaining() == 0 {
445 return Err(Error::ErrShortPacket);
446 }
447 let b = reader.get_u8();
448 payload_index += 1;
449
450 self.pgtid.push(b >> 5);
451 self.pgu.push(b & 0x10 != 0);
452
453 let r = ((b >> 2) & 0x3) as usize;
454 if reader.remaining() < r {
455 return Err(Error::ErrShortPacket);
456 }
457
458 self.pgpdiff.push(vec![]);
459 for _ in 0..r {
460 let b = reader.get_u8();
461 payload_index += 1;
462
463 self.pgpdiff[i].push(b);
464 }
465 }
466
467 Ok(payload_index)
468 }
469}