Skip to main content

rtc_rtcp/transport_feedbacks/transport_layer_cc/
mod.rs

1#[cfg(test)]
2mod transport_layer_cc_test;
3
4use crate::{header::*, packet::*, util::*};
5use shared::{
6    error::{Error, Result},
7    marshal::{Marshal, MarshalSize, Unmarshal},
8};
9
10use bytes::{Buf, BufMut};
11use std::any::Any;
12use std::fmt;
13
14/// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5>
15/// 0                   1                   2                   3
16/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
17/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18/// |V=2|P|  FMT=15 |    PT=205     |           length              |
19/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20/// |                     SSRC of packet sender                     |
21/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22/// |                      SSRC of media source                     |
23/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24/// |      base sequence number     |      packet status count      |
25/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26/// |                 reference time                | fb pkt. count |
27/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28/// |          packet chunk         |         packet chunk          |
29/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30/// .                                                               .
31/// .                                                               .
32/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33/// |         packet chunk          |  recv delta   |  recv delta   |
34/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35/// .                                                               .
36/// .                                                               .
37/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38/// |           recv delta          |  recv delta   | zero padding  |
39/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40// for packet status chunk
41/// type of packet status chunk
42///
43/// ## Specifications
44///
45/// * [draft-holmer-rmcat-transport-wide-cc-extensions-01, page 5]
46///
47/// [draft-holmer-rmcat-transport-wide-cc-extensions-01, page 5]: https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
48#[derive(Default, PartialEq, Eq, Debug, Clone)]
49#[repr(u16)]
50pub enum StatusChunkTypeTcc {
51    #[default]
52    RunLengthChunk = 0,
53    StatusVectorChunk = 1,
54}
55
56/// type of packet status symbol and recv delta
57#[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
58#[repr(u16)]
59pub enum SymbolTypeTcc {
60    /// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.1>
61    #[default]
62    PacketNotReceived = 0,
63    /// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.1>
64    PacketReceivedSmallDelta = 1,
65    /// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.1>
66    PacketReceivedLargeDelta = 2,
67    /// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-7>
68    /// see Example 2: "packet received, w/o recv delta"
69    PacketReceivedWithoutDelta = 3,
70}
71
72/// for status vector chunk
73#[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
74#[repr(u16)]
75pub enum SymbolSizeTypeTcc {
76    /// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.4>
77    #[default]
78    OneBit = 0,
79    TwoBit = 1,
80}
81
82impl From<u16> for SymbolSizeTypeTcc {
83    fn from(val: u16) -> Self {
84        match val {
85            0 => SymbolSizeTypeTcc::OneBit,
86            _ => SymbolSizeTypeTcc::TwoBit,
87        }
88    }
89}
90
91impl From<u16> for StatusChunkTypeTcc {
92    fn from(val: u16) -> Self {
93        match val {
94            0 => StatusChunkTypeTcc::RunLengthChunk,
95            _ => StatusChunkTypeTcc::StatusVectorChunk,
96        }
97    }
98}
99
100impl From<u16> for SymbolTypeTcc {
101    fn from(val: u16) -> Self {
102        match val {
103            0 => SymbolTypeTcc::PacketNotReceived,
104            1 => SymbolTypeTcc::PacketReceivedSmallDelta,
105            2 => SymbolTypeTcc::PacketReceivedLargeDelta,
106            _ => SymbolTypeTcc::PacketReceivedWithoutDelta,
107        }
108    }
109}
110
111/// PacketStatusChunk has two kinds:
112/// RunLengthChunk and StatusVectorChunk
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub enum PacketStatusChunk {
115    RunLengthChunk(RunLengthChunk),
116    StatusVectorChunk(StatusVectorChunk),
117}
118
119impl MarshalSize for PacketStatusChunk {
120    fn marshal_size(&self) -> usize {
121        match self {
122            PacketStatusChunk::RunLengthChunk(c) => c.marshal_size(),
123            PacketStatusChunk::StatusVectorChunk(c) => c.marshal_size(),
124        }
125    }
126}
127
128impl Marshal for PacketStatusChunk {
129    /// Marshal ..
130    fn marshal_to(&self, buf: &mut [u8]) -> Result<usize> {
131        match self {
132            PacketStatusChunk::RunLengthChunk(c) => c.marshal_to(buf),
133            PacketStatusChunk::StatusVectorChunk(c) => c.marshal_to(buf),
134        }
135    }
136}
137
138/// RunLengthChunk T=TypeTCCRunLengthChunk
139/// 0                   1
140/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
141/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142/// |T| S |       Run Length        |
143/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144#[derive(Debug, Clone, PartialEq, Eq, Default)]
145pub struct RunLengthChunk {
146    /// T = TypeTCCRunLengthChunk
147    pub type_tcc: StatusChunkTypeTcc,
148    /// S: type of packet status
149    /// kind: TypeTCCPacketNotReceived or...
150    pub packet_status_symbol: SymbolTypeTcc,
151    /// run_length: count of S
152    pub run_length: u16,
153}
154
155impl MarshalSize for RunLengthChunk {
156    fn marshal_size(&self) -> usize {
157        PACKET_STATUS_CHUNK_LENGTH
158    }
159}
160
161impl Marshal for RunLengthChunk {
162    /// Marshal ..
163    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
164        // append 1 bit '0'
165        let mut dst = set_nbits_of_uint16(0, 1, 0, 0)?;
166
167        // append 2 bit packet_status_symbol
168        dst = set_nbits_of_uint16(dst, 2, 1, self.packet_status_symbol as u16)?;
169
170        // append 13 bit run_length
171        dst = set_nbits_of_uint16(dst, 13, 3, self.run_length)?;
172
173        buf.put_u16(dst);
174
175        Ok(PACKET_STATUS_CHUNK_LENGTH)
176    }
177}
178
179impl Unmarshal for RunLengthChunk {
180    /// Unmarshal ..
181    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
182    where
183        Self: Sized,
184        B: Buf,
185    {
186        let raw_packet_len = raw_packet.remaining();
187        if raw_packet_len < PACKET_STATUS_CHUNK_LENGTH {
188            return Err(Error::PacketStatusChunkLength);
189        }
190
191        // record type
192        let type_tcc = StatusChunkTypeTcc::RunLengthChunk;
193
194        let b0 = raw_packet.get_u8();
195        let b1 = raw_packet.get_u8();
196
197        // get PacketStatusSymbol
198        let packet_status_symbol = get_nbits_from_byte(b0, 1, 2).into();
199
200        // get RunLength
201        let run_length = ((get_nbits_from_byte(b0, 3, 5) as usize) << 8) as u16 + (b1 as u16);
202
203        Ok(RunLengthChunk {
204            type_tcc,
205            packet_status_symbol,
206            run_length,
207        })
208    }
209}
210
211/// StatusVectorChunk T=typeStatusVectorChunk
212/// 0                   1
213/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
214/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215/// |T|S|       symbol list         |
216/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217#[derive(Debug, Clone, PartialEq, Eq, Default)]
218pub struct StatusVectorChunk {
219    /// T = TypeTCCRunLengthChunk
220    pub type_tcc: StatusChunkTypeTcc,
221
222    /// TypeTCCSymbolSizeOneBit or TypeTCCSymbolSizeTwoBit
223    pub symbol_size: SymbolSizeTypeTcc,
224
225    /// when symbol_size = TypeTCCSymbolSizeOneBit, symbol_list is 14*1bit:
226    /// TypeTCCSymbolListPacketReceived or TypeTCCSymbolListPacketNotReceived
227    /// when symbol_size = TypeTCCSymbolSizeTwoBit, symbol_list is 7*2bit:
228    /// TypeTCCPacketNotReceived TypeTCCPacketReceivedSmallDelta TypeTCCPacketReceivedLargeDelta or typePacketReserved
229    pub symbol_list: Vec<SymbolTypeTcc>,
230}
231
232impl MarshalSize for StatusVectorChunk {
233    fn marshal_size(&self) -> usize {
234        PACKET_STATUS_CHUNK_LENGTH
235    }
236}
237
238impl Marshal for StatusVectorChunk {
239    /// Marshal ..
240    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
241        // set first bit '1'
242        let mut dst = set_nbits_of_uint16(0, 1, 0, 1)?;
243
244        // set second bit symbol_size
245        dst = set_nbits_of_uint16(dst, 1, 1, self.symbol_size as u16)?;
246
247        let num_of_bits = NUM_OF_BITS_OF_SYMBOL_SIZE[self.symbol_size as usize];
248        // append 14 bit symbol_list
249        for (i, s) in self.symbol_list.iter().enumerate() {
250            let index = num_of_bits * (i as u16) + 2;
251            dst = set_nbits_of_uint16(dst, num_of_bits, index, *s as u16)?;
252        }
253
254        buf.put_u16(dst);
255
256        Ok(PACKET_STATUS_CHUNK_LENGTH)
257    }
258}
259
260impl Unmarshal for StatusVectorChunk {
261    /// Unmarshal ..
262    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
263    where
264        Self: Sized,
265        B: Buf,
266    {
267        let raw_packet_len = raw_packet.remaining();
268        if raw_packet_len < PACKET_STATUS_CHUNK_LENGTH {
269            return Err(Error::PacketBeforeCname);
270        }
271
272        let type_tcc = StatusChunkTypeTcc::StatusVectorChunk;
273
274        let b0 = raw_packet.get_u8();
275        let b1 = raw_packet.get_u8();
276
277        let symbol_size = get_nbits_from_byte(b0, 1, 1).into();
278
279        let mut symbol_list: Vec<SymbolTypeTcc> = vec![];
280        match symbol_size {
281            SymbolSizeTypeTcc::OneBit => {
282                for i in 0..6u16 {
283                    symbol_list.push(get_nbits_from_byte(b0, 2 + i, 1).into());
284                }
285
286                for i in 0..8u16 {
287                    symbol_list.push(get_nbits_from_byte(b1, i, 1).into())
288                }
289            }
290
291            SymbolSizeTypeTcc::TwoBit => {
292                for i in 0..3u16 {
293                    symbol_list.push(get_nbits_from_byte(b0, 2 + i * 2, 2).into());
294                }
295
296                for i in 0..4u16 {
297                    symbol_list.push(get_nbits_from_byte(b1, i * 2, 2).into());
298                }
299            }
300        }
301
302        Ok(StatusVectorChunk {
303            type_tcc,
304            symbol_size,
305            symbol_list,
306        })
307    }
308}
309
310/// RecvDelta are represented as multiples of 250us
311/// small delta is 1 byte: [0,63.75]ms = [0, 63750]us = [0, 255]*250us
312/// big delta is 2 bytes: [-8192.0, 8191.75]ms = [-8192000, 8191750]us = [-32768, 32767]*250us
313/// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.5>
314#[derive(Debug, Clone, PartialEq, Eq, Default)]
315pub struct RecvDelta {
316    pub type_tcc_packet: SymbolTypeTcc,
317    /// us
318    pub delta: i64,
319}
320
321impl MarshalSize for RecvDelta {
322    fn marshal_size(&self) -> usize {
323        let delta = self.delta / TYPE_TCC_DELTA_SCALE_FACTOR;
324
325        // small delta
326        if self.type_tcc_packet == SymbolTypeTcc::PacketReceivedSmallDelta
327            && delta >= 0
328            && delta <= u8::MAX as i64
329        {
330            return 1;
331        }
332
333        // big delta
334        if self.type_tcc_packet == SymbolTypeTcc::PacketReceivedLargeDelta
335            && delta >= i16::MIN as i64
336            && delta <= i16::MAX as i64
337        {
338            return 2;
339        }
340
341        0
342    }
343}
344
345impl Marshal for RecvDelta {
346    /// Marshal ..
347    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
348        let delta = self.delta / TYPE_TCC_DELTA_SCALE_FACTOR;
349
350        // small delta
351        if self.type_tcc_packet == SymbolTypeTcc::PacketReceivedSmallDelta
352            && delta >= 0
353            && delta <= u8::MAX as i64
354            && buf.remaining_mut() >= 1
355        {
356            buf.put_u8(delta as u8);
357            return Ok(1);
358        }
359
360        // big delta
361        if self.type_tcc_packet == SymbolTypeTcc::PacketReceivedLargeDelta
362            && delta >= i16::MIN as i64
363            && delta <= i16::MAX as i64
364            && buf.remaining_mut() >= 2
365        {
366            buf.put_i16(delta as i16);
367            return Ok(2);
368        }
369
370        // overflow
371        Err(Error::DeltaExceedLimit)
372    }
373}
374
375impl Unmarshal for RecvDelta {
376    /// Unmarshal ..
377    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
378    where
379        Self: Sized,
380        B: Buf,
381    {
382        let chunk_len = raw_packet.remaining();
383
384        // must be 1 or 2 bytes
385        if chunk_len != 1 && chunk_len != 2 {
386            return Err(Error::DeltaExceedLimit);
387        }
388
389        let (type_tcc_packet, delta) = if chunk_len == 1 {
390            (
391                SymbolTypeTcc::PacketReceivedSmallDelta,
392                TYPE_TCC_DELTA_SCALE_FACTOR * raw_packet.get_u8() as i64,
393            )
394        } else {
395            (
396                SymbolTypeTcc::PacketReceivedLargeDelta,
397                TYPE_TCC_DELTA_SCALE_FACTOR * raw_packet.get_i16() as i64,
398            )
399        };
400
401        Ok(RecvDelta {
402            type_tcc_packet,
403            delta,
404        })
405    }
406}
407
408/// The offset after header
409const BASE_SEQUENCE_NUMBER_OFFSET: usize = 8;
410/// The offset after header
411const PACKET_STATUS_COUNT_OFFSET: usize = 10;
412/// The offset after header
413const REFERENCE_TIME_OFFSET: usize = 12;
414/// The offset after header
415const FB_PKT_COUNT_OFFSET: usize = 15;
416/// The offset after header
417const PACKET_CHUNK_OFFSET: usize = 16;
418/// len of packet status chunk
419const TYPE_TCC_STATUS_VECTOR_CHUNK: usize = 1;
420
421/// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1.5>
422pub const TYPE_TCC_DELTA_SCALE_FACTOR: i64 = 250;
423
424// Notice: RFC is wrong: "packet received" (0) and "packet not received" (1)
425// if S == TYPE_TCCSYMBOL_SIZE_ONE_BIT, symbol list will be: TypeTCCPacketNotReceived TypeTCCPacketReceivedSmallDelta
426// if S == TYPE_TCCSYMBOL_SIZE_TWO_BIT, symbol list will be same as above:
427
428static NUM_OF_BITS_OF_SYMBOL_SIZE: [u16; 2] = [1, 2];
429
430/// len of packet status chunk
431const PACKET_STATUS_CHUNK_LENGTH: usize = 2;
432
433/// TransportLayerCC for sender-BWE
434/// <https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5>
435#[derive(Debug, Default, PartialEq, Eq, Clone)]
436pub struct TransportLayerCc {
437    /// SSRC of sender
438    pub sender_ssrc: u32,
439    /// SSRC of the media source
440    pub media_ssrc: u32,
441    /// Transport wide sequence of rtp extension
442    pub base_sequence_number: u16,
443    /// packet_status_count
444    pub packet_status_count: u16,
445    /// reference_time
446    pub reference_time: u32,
447    /// fb_pkt_count
448    pub fb_pkt_count: u8,
449    /// packet_chunks
450    pub packet_chunks: Vec<PacketStatusChunk>,
451    /// recv_deltas
452    pub recv_deltas: Vec<RecvDelta>,
453}
454
455impl fmt::Display for TransportLayerCc {
456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457        let mut out = String::new();
458        out += format!("TransportLayerCC:\n\tSender Ssrc {}\n", self.sender_ssrc).as_str();
459        out += format!("\tMedia Ssrc {}\n", self.media_ssrc).as_str();
460        out += format!("\tBase Sequence Number {}\n", self.base_sequence_number).as_str();
461        out += format!("\tStatus Count {}\n", self.packet_status_count).as_str();
462        out += format!("\tReference Time {}\n", self.reference_time).as_str();
463        out += format!("\tFeedback Packet Count {}\n", self.fb_pkt_count).as_str();
464        out += "\tpacket_chunks ";
465        out += "\n\trecv_deltas ";
466        for delta in &self.recv_deltas {
467            out += format!("{delta:?} ").as_str();
468        }
469        out += "\n";
470
471        write!(f, "{out}")
472    }
473}
474
475impl Packet for TransportLayerCc {
476    fn header(&self) -> Header {
477        Header {
478            padding: get_padding_size(self.raw_size()) != 0,
479            count: FORMAT_TCC,
480            packet_type: PacketType::TransportSpecificFeedback,
481            length: ((self.marshal_size() / 4) - 1) as u16,
482        }
483    }
484
485    /// destination_ssrc returns an array of SSRC values that this packet refers to.
486    fn destination_ssrc(&self) -> Vec<u32> {
487        vec![self.media_ssrc]
488    }
489
490    fn raw_size(&self) -> usize {
491        let mut n = HEADER_LENGTH + PACKET_CHUNK_OFFSET + self.packet_chunks.len() * 2;
492        for d in &self.recv_deltas {
493            // small delta
494            if d.type_tcc_packet == SymbolTypeTcc::PacketReceivedSmallDelta {
495                n += 1;
496            } else {
497                n += 2
498            }
499        }
500        n
501    }
502
503    fn as_any(&self) -> &dyn Any {
504        self
505    }
506
507    fn equal(&self, other: &dyn Packet) -> bool {
508        other.as_any().downcast_ref::<TransportLayerCc>() == Some(self)
509    }
510
511    fn cloned(&self) -> Box<dyn Packet> {
512        Box::new(self.clone())
513    }
514}
515
516impl MarshalSize for TransportLayerCc {
517    fn marshal_size(&self) -> usize {
518        let l = self.raw_size();
519        // align to 32-bit boundary
520        l + get_padding_size(l)
521    }
522}
523
524impl Marshal for TransportLayerCc {
525    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
526        if buf.remaining_mut() < self.marshal_size() {
527            return Err(Error::BufferTooShort);
528        }
529
530        let h = self.header();
531        let n = h.marshal_to(buf)?;
532        buf = &mut buf[n..];
533
534        buf.put_u32(self.sender_ssrc);
535        buf.put_u32(self.media_ssrc);
536        buf.put_u16(self.base_sequence_number);
537        buf.put_u16(self.packet_status_count);
538
539        let reference_time_and_fb_pkt_count = append_nbits_to_uint32(0, 24, self.reference_time);
540        let reference_time_and_fb_pkt_count =
541            append_nbits_to_uint32(reference_time_and_fb_pkt_count, 8, self.fb_pkt_count as u32);
542
543        buf.put_u32(reference_time_and_fb_pkt_count);
544
545        for chunk in &self.packet_chunks {
546            let n = chunk.marshal_to(buf)?;
547            buf = &mut buf[n..];
548        }
549
550        for delta in &self.recv_deltas {
551            let n = delta.marshal_to(buf)?;
552            buf = &mut buf[n..];
553        }
554
555        if h.padding {
556            put_padding(buf, self.raw_size());
557        }
558
559        Ok(self.marshal_size())
560    }
561}
562
563impl Unmarshal for TransportLayerCc {
564    /// Unmarshal ..
565    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
566    where
567        Self: Sized,
568        B: Buf,
569    {
570        let raw_packet_len = raw_packet.remaining();
571        if raw_packet_len < (HEADER_LENGTH + SSRC_LENGTH) {
572            return Err(Error::PacketTooShort);
573        }
574
575        let h = Header::unmarshal(raw_packet)?;
576
577        // https://tools.ietf.org/html/rfc4585#page-33
578        // header's length + payload's length
579        let total_length = 4 * (h.length + 1) as usize;
580
581        if total_length < HEADER_LENGTH + PACKET_CHUNK_OFFSET {
582            return Err(Error::PacketTooShort);
583        }
584
585        if raw_packet_len < total_length {
586            return Err(Error::PacketTooShort);
587        }
588
589        if h.packet_type != PacketType::TransportSpecificFeedback || h.count != FORMAT_TCC {
590            return Err(Error::WrongType);
591        }
592
593        let sender_ssrc = raw_packet.get_u32();
594        let media_ssrc = raw_packet.get_u32();
595        let base_sequence_number = raw_packet.get_u16();
596        let packet_status_count = raw_packet.get_u16();
597
598        let mut buf = vec![0u8; 3];
599        buf[0] = raw_packet.get_u8();
600        buf[1] = raw_packet.get_u8();
601        buf[2] = raw_packet.get_u8();
602        let reference_time = get_24bits_from_bytes(&buf);
603        let fb_pkt_count = raw_packet.get_u8();
604        let mut packet_chunks = vec![];
605        let mut recv_deltas = vec![];
606
607        let mut packet_status_pos = HEADER_LENGTH + PACKET_CHUNK_OFFSET;
608        let mut processed_packet_num = 0u16;
609        while processed_packet_num < packet_status_count {
610            if packet_status_pos + PACKET_STATUS_CHUNK_LENGTH >= total_length {
611                return Err(Error::PacketTooShort);
612            }
613
614            let mut chunk_reader = raw_packet.copy_to_bytes(PACKET_STATUS_CHUNK_LENGTH);
615            let b0 = chunk_reader[0];
616
617            let typ = get_nbits_from_byte(b0, 0, 1);
618            let initial_packet_status: PacketStatusChunk;
619            match typ.into() {
620                StatusChunkTypeTcc::RunLengthChunk => {
621                    let packet_status = RunLengthChunk::unmarshal(&mut chunk_reader)?;
622
623                    let packet_number_to_process =
624                        (packet_status_count - processed_packet_num).min(packet_status.run_length);
625
626                    if packet_status.packet_status_symbol == SymbolTypeTcc::PacketReceivedSmallDelta
627                        || packet_status.packet_status_symbol
628                            == SymbolTypeTcc::PacketReceivedLargeDelta
629                    {
630                        let mut j = 0u16;
631
632                        while j < packet_number_to_process {
633                            recv_deltas.push(RecvDelta {
634                                type_tcc_packet: packet_status.packet_status_symbol,
635                                ..Default::default()
636                            });
637
638                            j += 1;
639                        }
640                    }
641
642                    initial_packet_status = PacketStatusChunk::RunLengthChunk(packet_status);
643                    processed_packet_num += packet_number_to_process;
644                }
645
646                StatusChunkTypeTcc::StatusVectorChunk => {
647                    let packet_status = StatusVectorChunk::unmarshal(&mut chunk_reader)?;
648
649                    match packet_status.symbol_size {
650                        SymbolSizeTypeTcc::OneBit => {
651                            for sym in &packet_status.symbol_list {
652                                if *sym == SymbolTypeTcc::PacketReceivedSmallDelta {
653                                    recv_deltas.push(RecvDelta {
654                                        type_tcc_packet: SymbolTypeTcc::PacketReceivedSmallDelta,
655                                        ..Default::default()
656                                    })
657                                }
658                            }
659                        }
660
661                        SymbolSizeTypeTcc::TwoBit => {
662                            for sym in &packet_status.symbol_list {
663                                if *sym == SymbolTypeTcc::PacketReceivedSmallDelta
664                                    || *sym == SymbolTypeTcc::PacketReceivedLargeDelta
665                                {
666                                    recv_deltas.push(RecvDelta {
667                                        type_tcc_packet: *sym,
668                                        ..Default::default()
669                                    })
670                                }
671                            }
672                        }
673                    }
674
675                    processed_packet_num += packet_status.symbol_list.len() as u16;
676                    initial_packet_status = PacketStatusChunk::StatusVectorChunk(packet_status);
677                }
678            }
679
680            packet_status_pos += PACKET_STATUS_CHUNK_LENGTH;
681            packet_chunks.push(initial_packet_status);
682        }
683
684        let mut recv_deltas_pos = packet_status_pos;
685
686        for delta in &mut recv_deltas {
687            if recv_deltas_pos >= total_length {
688                return Err(Error::PacketTooShort);
689            }
690
691            if delta.type_tcc_packet == SymbolTypeTcc::PacketReceivedSmallDelta {
692                let mut delta_reader = raw_packet.take(1);
693                *delta = RecvDelta::unmarshal(&mut delta_reader)?;
694                recv_deltas_pos += 1;
695            }
696
697            if delta.type_tcc_packet == SymbolTypeTcc::PacketReceivedLargeDelta {
698                let mut delta_reader = raw_packet.take(2);
699                *delta = RecvDelta::unmarshal(&mut delta_reader)?;
700                recv_deltas_pos += 2;
701            }
702        }
703
704        if
705        /*h.padding &&*/
706        raw_packet.has_remaining() {
707            raw_packet.advance(raw_packet.remaining());
708        }
709
710        Ok(TransportLayerCc {
711            sender_ssrc,
712            media_ssrc,
713            base_sequence_number,
714            packet_status_count,
715            reference_time,
716            fb_pkt_count,
717            packet_chunks,
718            recv_deltas,
719        })
720    }
721}