1 #[cfg(test)] 2 mod vp9_test; 3 4 use crate::{ 5 error::{Error, Result}, 6 packetizer::{Depacketizer, Payloader}, 7 }; 8 9 use bytes::{Buf, BufMut, Bytes, BytesMut}; 10 use std::fmt; 11 use std::sync::Arc; 12 13 /// Flexible mode 15 bit picture ID 14 const VP9HEADER_SIZE: usize = 3; 15 const MAX_SPATIAL_LAYERS: u8 = 5; 16 const MAX_VP9REF_PICS: usize = 3; 17 18 /// InitialPictureIDFn is a function that returns random initial picture ID. 19 pub type InitialPictureIDFn = Arc<dyn (Fn() -> u16) + Send + Sync>; 20 21 /// Vp9Payloader payloads VP9 packets 22 #[derive(Default, Clone)] 23 pub struct Vp9Payloader { 24 picture_id: u16, 25 initialized: bool, 26 27 pub initial_picture_id_fn: Option<InitialPictureIDFn>, 28 } 29 30 impl fmt::Debug for Vp9Payloader { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 32 f.debug_struct("Vp9Payloader") 33 .field("picture_id", &self.picture_id) 34 .field("initialized", &self.initialized) 35 .finish() 36 } 37 } 38 39 impl Payloader for Vp9Payloader { 40 /// Payload fragments an Vp9Payloader packet across one or more byte arrays payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>>41 fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> { 42 /* 43 * https://www.ietf.org/id/draft-ietf-payload-vp9-13.txt 44 * 45 * Flexible mode (F=1) 46 * 0 1 2 3 4 5 6 7 47 * +-+-+-+-+-+-+-+-+ 48 * |I|P|L|F|B|E|V|Z| (REQUIRED) 49 * +-+-+-+-+-+-+-+-+ 50 * I: |M| PICTURE ID | (REQUIRED) 51 * +-+-+-+-+-+-+-+-+ 52 * M: | EXTENDED PID | (RECOMMENDED) 53 * +-+-+-+-+-+-+-+-+ 54 * L: | tid |U| SID |D| (CONDITIONALLY RECOMMENDED) 55 * +-+-+-+-+-+-+-+-+ -\ 56 * P,F: | P_DIFF |N| (CONDITIONALLY REQUIRED) - up to 3 times 57 * +-+-+-+-+-+-+-+-+ -/ 58 * V: | SS | 59 * | .. | 60 * +-+-+-+-+-+-+-+-+ 61 * 62 * Non-flexible mode (F=0) 63 * 0 1 2 3 4 5 6 7 64 * +-+-+-+-+-+-+-+-+ 65 * |I|P|L|F|B|E|V|Z| (REQUIRED) 66 * +-+-+-+-+-+-+-+-+ 67 * I: |M| PICTURE ID | (RECOMMENDED) 68 * +-+-+-+-+-+-+-+-+ 69 * M: | EXTENDED PID | (RECOMMENDED) 70 * +-+-+-+-+-+-+-+-+ 71 * L: | tid |U| SID |D| (CONDITIONALLY RECOMMENDED) 72 * +-+-+-+-+-+-+-+-+ 73 * | tl0picidx | (CONDITIONALLY REQUIRED) 74 * +-+-+-+-+-+-+-+-+ 75 * V: | SS | 76 * | .. | 77 * +-+-+-+-+-+-+-+-+ 78 */ 79 80 if payload.is_empty() || mtu == 0 { 81 return Ok(vec![]); 82 } 83 84 if !self.initialized { 85 if self.initial_picture_id_fn.is_none() { 86 self.initial_picture_id_fn = 87 Some(Arc::new(|| -> u16 { rand::random::<u16>() & 0x7FFF })); 88 } 89 self.picture_id = if let Some(f) = &self.initial_picture_id_fn { 90 f() 91 } else { 92 0 93 }; 94 self.initialized = true; 95 } 96 97 let max_fragment_size = mtu as isize - VP9HEADER_SIZE as isize; 98 let mut payloads = vec![]; 99 let mut payload_data_remaining = payload.len(); 100 let mut payload_data_index = 0; 101 102 if std::cmp::min(max_fragment_size, payload_data_remaining as isize) <= 0 { 103 return Ok(vec![]); 104 } 105 106 while payload_data_remaining > 0 { 107 let current_fragment_size = 108 std::cmp::min(max_fragment_size as usize, payload_data_remaining); 109 let mut out = BytesMut::with_capacity(VP9HEADER_SIZE + current_fragment_size); 110 let mut buf = vec![0u8; VP9HEADER_SIZE]; 111 buf[0] = 0x90; // F=1 I=1 112 if payload_data_index == 0 { 113 buf[0] |= 0x08; // B=1 114 } 115 if payload_data_remaining == current_fragment_size { 116 buf[0] |= 0x04; // E=1 117 } 118 buf[1] = (self.picture_id >> 8) as u8 | 0x80; 119 buf[2] = (self.picture_id & 0xFF) as u8; 120 121 out.put(&buf[..]); 122 123 out.put( 124 &*payload.slice(payload_data_index..payload_data_index + current_fragment_size), 125 ); 126 127 payloads.push(out.freeze()); 128 129 payload_data_remaining -= current_fragment_size; 130 payload_data_index += current_fragment_size; 131 } 132 133 self.picture_id += 1; 134 self.picture_id &= 0x7FFF; 135 136 Ok(payloads) 137 } 138 clone_to(&self) -> Box<dyn Payloader + Send + Sync>139 fn clone_to(&self) -> Box<dyn Payloader + Send + Sync> { 140 Box::new(self.clone()) 141 } 142 } 143 144 /// Vp9Packet represents the VP9 header that is stored in the payload of an RTP Packet 145 #[derive(PartialEq, Eq, Debug, Default, Clone)] 146 pub struct Vp9Packet { 147 /// picture ID is present 148 pub i: bool, 149 /// inter-picture predicted frame. 150 pub p: bool, 151 /// layer indices present 152 pub l: bool, 153 /// flexible mode 154 pub f: bool, 155 /// start of frame. beginning of new vp9 frame 156 pub b: bool, 157 /// end of frame 158 pub e: bool, 159 /// scalability structure (SS) present 160 pub v: bool, 161 /// Not a reference frame for upper spatial layers 162 pub z: bool, 163 164 /// Recommended headers 165 /// 7 or 16 bits, picture ID. 166 pub picture_id: u16, 167 168 /// Conditionally recommended headers 169 /// Temporal layer ID 170 pub tid: u8, 171 /// Switching up point 172 pub u: bool, 173 /// Spatial layer ID 174 pub sid: u8, 175 /// Inter-layer dependency used 176 pub d: bool, 177 178 /// Conditionally required headers 179 /// Reference index (F=1) 180 pub pdiff: Vec<u8>, 181 /// Temporal layer zero index (F=0) 182 pub tl0picidx: u8, 183 184 /// Scalability structure headers 185 /// N_S + 1 indicates the number of spatial layers present in the VP9 stream 186 pub ns: u8, 187 /// Each spatial layer's frame resolution present 188 pub y: bool, 189 /// PG description present flag. 190 pub g: bool, 191 /// N_G indicates the number of pictures in a Picture Group (PG) 192 pub ng: u8, 193 pub width: Vec<u16>, 194 pub height: Vec<u16>, 195 /// Temporal layer ID of pictures in a Picture Group 196 pub pgtid: Vec<u8>, 197 /// Switching up point of pictures in a Picture Group 198 pub pgu: Vec<bool>, 199 /// Reference indecies of pictures in a Picture Group 200 pub pgpdiff: Vec<Vec<u8>>, 201 } 202 203 impl Depacketizer for Vp9Packet { 204 /// depacketize parses the passed byte slice and stores the result in the Vp9Packet this method is called upon depacketize(&mut self, packet: &Bytes) -> Result<Bytes>205 fn depacketize(&mut self, packet: &Bytes) -> Result<Bytes> { 206 if packet.is_empty() { 207 return Err(Error::ErrShortPacket); 208 } 209 210 let reader = &mut packet.clone(); 211 let b = reader.get_u8(); 212 213 self.i = (b & 0x80) != 0; 214 self.p = (b & 0x40) != 0; 215 self.l = (b & 0x20) != 0; 216 self.f = (b & 0x10) != 0; 217 self.b = (b & 0x08) != 0; 218 self.e = (b & 0x04) != 0; 219 self.v = (b & 0x02) != 0; 220 self.z = (b & 0x01) != 0; 221 222 let mut payload_index = 1; 223 224 if self.i { 225 payload_index = self.parse_picture_id(reader, payload_index)?; 226 } 227 228 if self.l { 229 payload_index = self.parse_layer_info(reader, payload_index)?; 230 } 231 232 if self.f && self.p { 233 payload_index = self.parse_ref_indices(reader, payload_index)?; 234 } 235 236 if self.v { 237 payload_index = self.parse_ssdata(reader, payload_index)?; 238 } 239 240 Ok(packet.slice(payload_index..)) 241 } 242 243 /// is_partition_head checks whether if this is a head of the VP9 partition is_partition_head(&self, payload: &Bytes) -> bool244 fn is_partition_head(&self, payload: &Bytes) -> bool { 245 if payload.is_empty() { 246 false 247 } else { 248 (payload[0] & 0x08) != 0 249 } 250 } 251 is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool252 fn is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool { 253 marker 254 } 255 } 256 257 impl Vp9Packet { 258 // Picture ID: 259 // 260 // +-+-+-+-+-+-+-+-+ 261 // I: |M| PICTURE ID | M:0 => picture id is 7 bits. 262 // +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. 263 // M: | EXTENDED PID | 264 // +-+-+-+-+-+-+-+-+ 265 // parse_picture_id( &mut self, reader: &mut dyn Buf, mut payload_index: usize, ) -> Result<usize>266 fn parse_picture_id( 267 &mut self, 268 reader: &mut dyn Buf, 269 mut payload_index: usize, 270 ) -> Result<usize> { 271 if reader.remaining() == 0 { 272 return Err(Error::ErrShortPacket); 273 } 274 let b = reader.get_u8(); 275 payload_index += 1; 276 // PID present? 277 if (b & 0x80) != 0 { 278 if reader.remaining() == 0 { 279 return Err(Error::ErrShortPacket); 280 } 281 // M == 1, PID is 15bit 282 self.picture_id = (((b & 0x7f) as u16) << 8) | (reader.get_u8() as u16); 283 payload_index += 1; 284 } else { 285 self.picture_id = (b & 0x7F) as u16; 286 } 287 288 Ok(payload_index) 289 } 290 parse_layer_info( &mut self, reader: &mut dyn Buf, mut payload_index: usize, ) -> Result<usize>291 fn parse_layer_info( 292 &mut self, 293 reader: &mut dyn Buf, 294 mut payload_index: usize, 295 ) -> Result<usize> { 296 payload_index = self.parse_layer_info_common(reader, payload_index)?; 297 298 if self.f { 299 Ok(payload_index) 300 } else { 301 self.parse_layer_info_non_flexible_mode(reader, payload_index) 302 } 303 } 304 305 // Layer indices (flexible mode): 306 // 307 // +-+-+-+-+-+-+-+-+ 308 // L: | T |U| S |D| 309 // +-+-+-+-+-+-+-+-+ 310 // parse_layer_info_common( &mut self, reader: &mut dyn Buf, mut payload_index: usize, ) -> Result<usize>311 fn parse_layer_info_common( 312 &mut self, 313 reader: &mut dyn Buf, 314 mut payload_index: usize, 315 ) -> Result<usize> { 316 if reader.remaining() == 0 { 317 return Err(Error::ErrShortPacket); 318 } 319 let b = reader.get_u8(); 320 payload_index += 1; 321 322 self.tid = b >> 5; 323 self.u = b & 0x10 != 0; 324 self.sid = (b >> 1) & 0x7; 325 self.d = b & 0x01 != 0; 326 327 if self.sid >= MAX_SPATIAL_LAYERS { 328 Err(Error::ErrTooManySpatialLayers) 329 } else { 330 Ok(payload_index) 331 } 332 } 333 334 // Layer indices (non-flexible mode): 335 // 336 // +-+-+-+-+-+-+-+-+ 337 // L: | T |U| S |D| 338 // +-+-+-+-+-+-+-+-+ 339 // | tl0picidx | 340 // +-+-+-+-+-+-+-+-+ 341 // parse_layer_info_non_flexible_mode( &mut self, reader: &mut dyn Buf, mut payload_index: usize, ) -> Result<usize>342 fn parse_layer_info_non_flexible_mode( 343 &mut self, 344 reader: &mut dyn Buf, 345 mut payload_index: usize, 346 ) -> Result<usize> { 347 if reader.remaining() == 0 { 348 return Err(Error::ErrShortPacket); 349 } 350 self.tl0picidx = reader.get_u8(); 351 payload_index += 1; 352 Ok(payload_index) 353 } 354 355 // Reference indices: 356 // 357 // +-+-+-+-+-+-+-+-+ P=1,F=1: At least one reference index 358 // P,F: | P_DIFF |N| up to 3 times has to be specified. 359 // +-+-+-+-+-+-+-+-+ N=1: An additional P_DIFF follows 360 // current P_DIFF. 361 // parse_ref_indices( &mut self, reader: &mut dyn Buf, mut payload_index: usize, ) -> Result<usize>362 fn parse_ref_indices( 363 &mut self, 364 reader: &mut dyn Buf, 365 mut payload_index: usize, 366 ) -> Result<usize> { 367 let mut b = 1u8; 368 while (b & 0x1) != 0 { 369 if reader.remaining() == 0 { 370 return Err(Error::ErrShortPacket); 371 } 372 b = reader.get_u8(); 373 payload_index += 1; 374 375 self.pdiff.push(b >> 1); 376 if self.pdiff.len() >= MAX_VP9REF_PICS { 377 return Err(Error::ErrTooManyPDiff); 378 } 379 } 380 381 Ok(payload_index) 382 } 383 384 // Scalability structure (SS): 385 // 386 // +-+-+-+-+-+-+-+-+ 387 // V: | N_S |Y|G|-|-|-| 388 // +-+-+-+-+-+-+-+-+ -| 389 // Y: | WIDTH | (OPTIONAL) . 390 // + + . 391 // | | (OPTIONAL) . 392 // +-+-+-+-+-+-+-+-+ . N_S + 1 times 393 // | HEIGHT | (OPTIONAL) . 394 // + + . 395 // | | (OPTIONAL) . 396 // +-+-+-+-+-+-+-+-+ -| 397 // G: | N_G | (OPTIONAL) 398 // +-+-+-+-+-+-+-+-+ -| 399 // N_G: | T |U| R |-|-| (OPTIONAL) . 400 // +-+-+-+-+-+-+-+-+ -| . N_G times 401 // | P_DIFF | (OPTIONAL) . R times . 402 // +-+-+-+-+-+-+-+-+ -| -| 403 // parse_ssdata(&mut self, reader: &mut dyn Buf, mut payload_index: usize) -> Result<usize>404 fn parse_ssdata(&mut self, reader: &mut dyn Buf, mut payload_index: usize) -> Result<usize> { 405 if reader.remaining() == 0 { 406 return Err(Error::ErrShortPacket); 407 } 408 409 let b = reader.get_u8(); 410 payload_index += 1; 411 412 self.ns = b >> 5; 413 self.y = b & 0x10 != 0; 414 self.g = (b >> 1) & 0x7 != 0; 415 416 let ns = (self.ns + 1) as usize; 417 self.ng = 0; 418 419 if self.y { 420 if reader.remaining() < 4 * ns { 421 return Err(Error::ErrShortPacket); 422 } 423 424 self.width = vec![0u16; ns]; 425 self.height = vec![0u16; ns]; 426 for i in 0..ns { 427 self.width[i] = reader.get_u16(); 428 self.height[i] = reader.get_u16(); 429 } 430 payload_index += 4 * ns; 431 } 432 433 if self.g { 434 if reader.remaining() == 0 { 435 return Err(Error::ErrShortPacket); 436 } 437 438 self.ng = reader.get_u8(); 439 payload_index += 1; 440 } 441 442 for i in 0..self.ng as usize { 443 if reader.remaining() == 0 { 444 return Err(Error::ErrShortPacket); 445 } 446 let b = reader.get_u8(); 447 payload_index += 1; 448 449 self.pgtid.push(b >> 5); 450 self.pgu.push(b & 0x10 != 0); 451 452 let r = ((b >> 2) & 0x3) as usize; 453 if reader.remaining() < r { 454 return Err(Error::ErrShortPacket); 455 } 456 457 self.pgpdiff.push(vec![]); 458 for _ in 0..r { 459 let b = reader.get_u8(); 460 payload_index += 1; 461 462 self.pgpdiff[i].push(b); 463 } 464 } 465 466 Ok(payload_index) 467 } 468 } 469