rtcp/payload_feedbacks/picture_loss_indication/
mod.rs1#[cfg(test)]
2mod picture_loss_indication_test;
3
4use std::any::Any;
5use std::fmt;
6
7use bytes::{Buf, BufMut};
8use util::marshal::{Marshal, MarshalSize, Unmarshal};
9
10use crate::error::Error;
11use crate::header::*;
12use crate::packet::*;
13use crate::util::*;
14
15type Result<T> = std::result::Result<T, util::Error>;
16
17const PLI_LENGTH: usize = 2;
18
19#[derive(Debug, PartialEq, Eq, Default, Clone)]
21pub struct PictureLossIndication {
22 pub sender_ssrc: u32,
24 pub media_ssrc: u32,
26}
27
28impl fmt::Display for PictureLossIndication {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 write!(
31 f,
32 "PictureLossIndication {:x} {:x}",
33 self.sender_ssrc, self.media_ssrc
34 )
35 }
36}
37
38impl Packet for PictureLossIndication {
39 fn header(&self) -> Header {
41 Header {
42 padding: get_padding_size(self.raw_size()) != 0,
43 count: FORMAT_PLI,
44 packet_type: PacketType::PayloadSpecificFeedback,
45 length: ((self.marshal_size() / 4) - 1) as u16,
46 }
47 }
48
49 fn destination_ssrc(&self) -> Vec<u32> {
51 vec![self.media_ssrc]
52 }
53
54 fn raw_size(&self) -> usize {
55 HEADER_LENGTH + SSRC_LENGTH * 2
56 }
57
58 fn as_any(&self) -> &(dyn Any + Send + Sync) {
59 self
60 }
61
62 fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
63 other.as_any().downcast_ref::<PictureLossIndication>() == Some(self)
64 }
65
66 fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
67 Box::new(self.clone())
68 }
69}
70
71impl MarshalSize for PictureLossIndication {
72 fn marshal_size(&self) -> usize {
73 let l = self.raw_size();
74 l + get_padding_size(l)
76 }
77}
78
79impl Marshal for PictureLossIndication {
80 fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
82 if buf.remaining_mut() < self.marshal_size() {
89 return Err(Error::BufferTooShort.into());
90 }
91
92 let h = self.header();
93 let n = h.marshal_to(buf)?;
94 buf = &mut buf[n..];
95
96 buf.put_u32(self.sender_ssrc);
97 buf.put_u32(self.media_ssrc);
98
99 if h.padding {
100 put_padding(buf, self.raw_size());
101 }
102
103 Ok(self.marshal_size())
104 }
105}
106
107impl Unmarshal for PictureLossIndication {
108 fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
110 where
111 Self: Sized,
112 B: Buf,
113 {
114 let raw_packet_len = raw_packet.remaining();
115 if raw_packet_len < (HEADER_LENGTH + (SSRC_LENGTH * 2)) {
116 return Err(Error::PacketTooShort.into());
117 }
118
119 let h = Header::unmarshal(raw_packet)?;
120 if h.packet_type != PacketType::PayloadSpecificFeedback || h.count != FORMAT_PLI {
121 return Err(Error::WrongType.into());
122 }
123
124 let sender_ssrc = raw_packet.get_u32();
125 let media_ssrc = raw_packet.get_u32();
126
127 if
128 raw_packet.has_remaining() {
130 raw_packet.advance(raw_packet.remaining());
131 }
132
133 Ok(PictureLossIndication {
134 sender_ssrc,
135 media_ssrc,
136 })
137 }
138}