rtcp/payload_feedbacks/picture_loss_indication/
mod.rs

1#[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/// The PictureLossIndication packet informs the encoder about the loss of an undefined amount of coded video data belonging to one or more pictures
20#[derive(Debug, PartialEq, Eq, Default, Clone)]
21pub struct PictureLossIndication {
22    /// SSRC of sender
23    pub sender_ssrc: u32,
24    /// SSRC where the loss was experienced
25    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    /// Header returns the Header associated with this packet.
40    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    /// destination_ssrc returns an array of SSRC values that this packet refers to.
50    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        // align to 32-bit boundary
75        l + get_padding_size(l)
76    }
77}
78
79impl Marshal for PictureLossIndication {
80    /// Marshal encodes the PictureLossIndication in binary
81    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
82        /*
83         * PLI does not require parameters.  Therefore, the length field MUST be
84         * 2, and there MUST NOT be any Feedback Control Information.
85         *
86         * The semantics of this FB message is independent of the payload type.
87         */
88        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    /// Unmarshal decodes the PictureLossIndication from binary
109    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        /*h.padding &&*/
129        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}