1 #[cfg(test)] 2 mod slice_loss_indication_test; 3 4 use crate::{error::Error, header::*, packet::*, util::*}; 5 use util::marshal::{Marshal, MarshalSize, Unmarshal}; 6 7 use bytes::{Buf, BufMut}; 8 use std::any::Any; 9 use std::fmt; 10 11 type Result<T> = std::result::Result<T, util::Error>; 12 13 const SLI_LENGTH: usize = 2; 14 const SLI_OFFSET: usize = 8; 15 16 /// SLIEntry represents a single entry to the SLI packet's 17 /// list of lost slices. 18 #[derive(Debug, PartialEq, Eq, Default, Clone)] 19 pub struct SliEntry { 20 /// ID of first lost slice 21 pub first: u16, 22 /// Number of lost slices 23 pub number: u16, 24 /// ID of related picture 25 pub picture: u8, 26 } 27 28 /// The SliceLossIndication packet informs the encoder about the loss of a picture slice 29 #[derive(Debug, PartialEq, Eq, Default, Clone)] 30 pub struct SliceLossIndication { 31 /// SSRC of sender 32 pub sender_ssrc: u32, 33 /// SSRC of the media source 34 pub media_ssrc: u32, 35 36 pub sli_entries: Vec<SliEntry>, 37 } 38 39 impl fmt::Display for SliceLossIndication { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 41 write!( 42 f, 43 "SliceLossIndication {:x} {:x} {:?}", 44 self.sender_ssrc, self.media_ssrc, self.sli_entries, 45 ) 46 } 47 } 48 49 impl Packet for SliceLossIndication { 50 /// Header returns the Header associated with this packet. header(&self) -> Header51 fn header(&self) -> Header { 52 Header { 53 padding: get_padding_size(self.raw_size()) != 0, 54 count: FORMAT_SLI, 55 packet_type: PacketType::TransportSpecificFeedback, 56 length: ((self.marshal_size() / 4) - 1) as u16, 57 } 58 } 59 60 /// destination_ssrc returns an array of SSRC values that this packet refers to. destination_ssrc(&self) -> Vec<u32>61 fn destination_ssrc(&self) -> Vec<u32> { 62 vec![self.media_ssrc] 63 } 64 raw_size(&self) -> usize65 fn raw_size(&self) -> usize { 66 HEADER_LENGTH + SLI_OFFSET + self.sli_entries.len() * 4 67 } 68 as_any(&self) -> &(dyn Any + Send + Sync)69 fn as_any(&self) -> &(dyn Any + Send + Sync) { 70 self 71 } 72 equal(&self, other: &(dyn Packet + Send + Sync)) -> bool73 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { 74 other 75 .as_any() 76 .downcast_ref::<SliceLossIndication>() 77 .map_or(false, |a| self == a) 78 } 79 cloned(&self) -> Box<dyn Packet + Send + Sync>80 fn cloned(&self) -> Box<dyn Packet + Send + Sync> { 81 Box::new(self.clone()) 82 } 83 } 84 85 impl MarshalSize for SliceLossIndication { marshal_size(&self) -> usize86 fn marshal_size(&self) -> usize { 87 let l = self.raw_size(); 88 // align to 32-bit boundary 89 l + get_padding_size(l) 90 } 91 } 92 93 impl Marshal for SliceLossIndication { 94 /// Marshal encodes the SliceLossIndication in binary marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>95 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { 96 if (self.sli_entries.len() + SLI_LENGTH) as u8 > std::u8::MAX { 97 return Err(Error::TooManyReports.into()); 98 } 99 if buf.remaining_mut() < self.marshal_size() { 100 return Err(Error::BufferTooShort.into()); 101 } 102 103 let h = self.header(); 104 let n = h.marshal_to(buf)?; 105 buf = &mut buf[n..]; 106 107 buf.put_u32(self.sender_ssrc); 108 buf.put_u32(self.media_ssrc); 109 110 for s in &self.sli_entries { 111 let sli = ((s.first as u32 & 0x1FFF) << 19) 112 | ((s.number as u32 & 0x1FFF) << 6) 113 | (s.picture as u32 & 0x3F); 114 115 buf.put_u32(sli); 116 } 117 118 if h.padding { 119 put_padding(buf, self.raw_size()); 120 } 121 122 Ok(self.marshal_size()) 123 } 124 } 125 126 impl Unmarshal for SliceLossIndication { 127 /// Unmarshal decodes the SliceLossIndication from binary unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,128 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> 129 where 130 Self: Sized, 131 B: Buf, 132 { 133 let raw_packet_len = raw_packet.remaining(); 134 if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) { 135 return Err(Error::PacketTooShort.into()); 136 } 137 138 let h = Header::unmarshal(raw_packet)?; 139 140 if raw_packet_len < (HEADER_LENGTH + (4 * h.length as usize)) { 141 return Err(Error::PacketTooShort.into()); 142 } 143 144 if h.packet_type != PacketType::TransportSpecificFeedback || h.count != FORMAT_SLI { 145 return Err(Error::WrongType.into()); 146 } 147 148 let sender_ssrc = raw_packet.get_u32(); 149 let media_ssrc = raw_packet.get_u32(); 150 151 let mut i = HEADER_LENGTH + SLI_OFFSET; 152 let mut sli_entries = vec![]; 153 while i < HEADER_LENGTH + h.length as usize * 4 { 154 let sli = raw_packet.get_u32(); 155 sli_entries.push(SliEntry { 156 first: ((sli >> 19) & 0x1FFF) as u16, 157 number: ((sli >> 6) & 0x1FFF) as u16, 158 picture: (sli & 0x3F) as u8, 159 }); 160 161 i += 4; 162 } 163 164 if 165 /*h.padding &&*/ 166 raw_packet.has_remaining() { 167 raw_packet.advance(raw_packet.remaining()); 168 } 169 170 Ok(SliceLossIndication { 171 sender_ssrc, 172 media_ssrc, 173 sli_entries, 174 }) 175 } 176 } 177