1 #[cfg(test)] 2 mod vp8_test; 3 4 use crate::{ 5 error::{Error, Result}, 6 packetizer::{Depacketizer, Payloader}, 7 }; 8 9 use bytes::{Buf, BufMut, Bytes, BytesMut}; 10 11 pub const VP8_HEADER_SIZE: usize = 1; 12 13 /// Vp8Payloader payloads VP8 packets 14 #[derive(Default, Debug, Copy, Clone)] 15 pub struct Vp8Payloader { 16 pub enable_picture_id: bool, 17 picture_id: u16, 18 } 19 20 impl Payloader for Vp8Payloader { 21 /// Payload fragments a VP8 packet across one or more byte arrays payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>>22 fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> { 23 if payload.is_empty() || mtu == 0 { 24 return Ok(vec![]); 25 } 26 27 /* 28 * https://tools.ietf.org/html/rfc7741#section-4.2 29 * 30 * 0 1 2 3 4 5 6 7 31 * +-+-+-+-+-+-+-+-+ 32 * |X|R|N|S|R| PID | (REQUIRED) 33 * +-+-+-+-+-+-+-+-+ 34 * X: |I|L|T|K| RSV | (OPTIONAL) 35 * +-+-+-+-+-+-+-+-+ 36 * I: |M| PictureID | (OPTIONAL) 37 * +-+-+-+-+-+-+-+-+ 38 * L: | tl0picidx | (OPTIONAL) 39 * +-+-+-+-+-+-+-+-+ 40 * T/K: |tid|Y| KEYIDX | (OPTIONAL) 41 * +-+-+-+-+-+-+-+-+ 42 * S: Start of VP8 partition. SHOULD be set to 1 when the first payload 43 * octet of the RTP packet is the beginning of a new VP8 partition, 44 * and MUST NOT be 1 otherwise. The S bit MUST be set to 1 for the 45 * first packet of each encoded frame. 46 */ 47 let using_header_size = if self.enable_picture_id { 48 if self.picture_id == 0 || self.picture_id < 128 { 49 VP8_HEADER_SIZE + 2 50 } else { 51 VP8_HEADER_SIZE + 3 52 } 53 } else { 54 VP8_HEADER_SIZE 55 }; 56 57 let max_fragment_size = mtu as isize - using_header_size as isize; 58 let mut payload_data_remaining = payload.len() as isize; 59 let mut payload_data_index: usize = 0; 60 let mut payloads = vec![]; 61 62 // Make sure the fragment/payload size is correct 63 if std::cmp::min(max_fragment_size, payload_data_remaining) <= 0 { 64 return Ok(payloads); 65 } 66 67 let mut first = true; 68 while payload_data_remaining > 0 { 69 let current_fragment_size = 70 std::cmp::min(max_fragment_size, payload_data_remaining) as usize; 71 let mut out = BytesMut::with_capacity(using_header_size + current_fragment_size); 72 let mut buf = vec![0u8; 4]; 73 if first { 74 buf[0] = 0x10; 75 first = false; 76 } 77 78 if self.enable_picture_id { 79 if using_header_size == VP8_HEADER_SIZE + 2 { 80 buf[0] |= 0x80; 81 buf[1] |= 0x80; 82 buf[2] |= (self.picture_id & 0x7F) as u8; 83 } else if using_header_size == VP8_HEADER_SIZE + 3 { 84 buf[0] |= 0x80; 85 buf[1] |= 0x80; 86 buf[2] |= 0x80 | ((self.picture_id >> 8) & 0x7F) as u8; 87 buf[3] |= (self.picture_id & 0xFF) as u8; 88 } 89 } 90 91 out.put(&buf[..using_header_size]); 92 93 out.put( 94 &*payload.slice(payload_data_index..payload_data_index + current_fragment_size), 95 ); 96 payloads.push(out.freeze()); 97 98 payload_data_remaining -= current_fragment_size as isize; 99 payload_data_index += current_fragment_size; 100 } 101 102 self.picture_id += 1; 103 self.picture_id &= 0x7FFF; 104 105 Ok(payloads) 106 } 107 clone_to(&self) -> Box<dyn Payloader + Send + Sync>108 fn clone_to(&self) -> Box<dyn Payloader + Send + Sync> { 109 Box::new(*self) 110 } 111 } 112 113 /// Vp8Packet represents the VP8 header that is stored in the payload of an RTP Packet 114 #[derive(PartialEq, Eq, Debug, Default, Clone)] 115 pub struct Vp8Packet { 116 /// Required Header 117 /// extended controlbits present 118 pub x: u8, 119 /// when set to 1 this frame can be discarded 120 pub n: u8, 121 /// start of VP8 partition 122 pub s: u8, 123 /// partition index 124 pub pid: u8, 125 126 /// Extended control bits 127 /// 1 if PictureID is present 128 pub i: u8, 129 /// 1 if tl0picidx is present 130 pub l: u8, 131 /// 1 if tid is present 132 pub t: u8, 133 /// 1 if KEYIDX is present 134 pub k: u8, 135 136 /// Optional extension 137 /// 8 or 16 bits, picture ID 138 pub picture_id: u16, 139 /// 8 bits temporal level zero index 140 pub tl0_pic_idx: u8, 141 /// 2 bits temporal layer index 142 pub tid: u8, 143 /// 1 bit layer sync bit 144 pub y: u8, 145 /// 5 bits temporal key frame index 146 pub key_idx: u8, 147 } 148 149 impl Depacketizer for Vp8Packet { 150 /// depacketize parses the passed byte slice and stores the result in the VP8Packet this method is called upon depacketize(&mut self, packet: &Bytes) -> Result<Bytes>151 fn depacketize(&mut self, packet: &Bytes) -> Result<Bytes> { 152 let payload_len = packet.len(); 153 if payload_len < 4 { 154 return Err(Error::ErrShortPacket); 155 } 156 // 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 157 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 158 // |X|R|N|S|R| PID | (REQUIRED) |X|R|N|S|R| PID | (REQUIRED) 159 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 160 // X: |I|L|T|K| RSV | (OPTIONAL) X: |I|L|T|K| RSV | (OPTIONAL) 161 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 162 // I: |M| PictureID | (OPTIONAL) I: |M| PictureID | (OPTIONAL) 163 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 164 // L: | tl0picidx | (OPTIONAL) | PictureID | 165 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 166 //T/K:|tid|Y| KEYIDX | (OPTIONAL) L: | tl0picidx | (OPTIONAL) 167 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 168 //T/K:|tid|Y| KEYIDX | (OPTIONAL) 169 // +-+-+-+-+-+-+-+-+ 170 171 let reader = &mut packet.clone(); 172 let mut payload_index = 0; 173 174 let mut b = reader.get_u8(); 175 payload_index += 1; 176 177 self.x = (b & 0x80) >> 7; 178 self.n = (b & 0x20) >> 5; 179 self.s = (b & 0x10) >> 4; 180 self.pid = b & 0x07; 181 182 if self.x == 1 { 183 b = reader.get_u8(); 184 payload_index += 1; 185 self.i = (b & 0x80) >> 7; 186 self.l = (b & 0x40) >> 6; 187 self.t = (b & 0x20) >> 5; 188 self.k = (b & 0x10) >> 4; 189 } 190 191 if self.i == 1 { 192 b = reader.get_u8(); 193 payload_index += 1; 194 // PID present? 195 if b & 0x80 > 0 { 196 // M == 1, PID is 16bit 197 self.picture_id = (((b & 0x7f) as u16) << 8) | (reader.get_u8() as u16); 198 payload_index += 1; 199 } else { 200 self.picture_id = b as u16; 201 } 202 } 203 204 if payload_index >= payload_len { 205 return Err(Error::ErrShortPacket); 206 } 207 208 if self.l == 1 { 209 self.tl0_pic_idx = reader.get_u8(); 210 payload_index += 1; 211 } 212 213 if payload_index >= payload_len { 214 return Err(Error::ErrShortPacket); 215 } 216 217 if self.t == 1 || self.k == 1 { 218 let b = reader.get_u8(); 219 if self.t == 1 { 220 self.tid = b >> 6; 221 self.y = (b >> 5) & 0x1; 222 } 223 if self.k == 1 { 224 self.key_idx = b & 0x1F; 225 } 226 payload_index += 1; 227 } 228 229 if payload_index >= packet.len() { 230 return Err(Error::ErrShortPacket); 231 } 232 233 Ok(packet.slice(payload_index..)) 234 } 235 236 /// is_partition_head checks whether if this is a head of the VP8 partition is_partition_head(&self, payload: &Bytes) -> bool237 fn is_partition_head(&self, payload: &Bytes) -> bool { 238 if payload.is_empty() { 239 false 240 } else { 241 (payload[0] & 0x10) != 0 242 } 243 } 244 is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool245 fn is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool { 246 marker 247 } 248 } 249