xref: /aosp_15_r20/external/webrtc/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
12 
13 #include "modules/rtp_rtcp/source/byte_io.h"
14 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
15 #include "rtc_base/checks.h"
16 #include "rtc_base/logging.h"
17 
18 namespace webrtc {
19 namespace rtcp {
20 
21 // Loss Notification
22 // -----------------
23 //     0                   1                   2                   3
24 //     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
25 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26 //    |V=2|P| FMT=15  |   PT=206      |             length            |
27 //    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
28 //  0 |                  SSRC of packet sender                        |
29 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 //  4 |                  SSRC of media source                         |
31 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 //  8 |  Unique identifier 'L' 'N' 'T' 'F'                            |
33 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 // 12 | Last Decoded Sequence Number  | Last Received SeqNum Delta  |D|
35 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 
LossNotification()37 LossNotification::LossNotification()
38     : last_decoded_(0), last_received_(0), decodability_flag_(false) {}
39 
LossNotification(uint16_t last_decoded,uint16_t last_received,bool decodability_flag)40 LossNotification::LossNotification(uint16_t last_decoded,
41                                    uint16_t last_received,
42                                    bool decodability_flag)
43     : last_decoded_(last_decoded),
44       last_received_(last_received),
45       decodability_flag_(decodability_flag) {}
46 
47 LossNotification::LossNotification(const LossNotification& rhs) = default;
48 
49 LossNotification::~LossNotification() = default;
50 
BlockLength() const51 size_t LossNotification::BlockLength() const {
52   return kHeaderLength + kCommonFeedbackLength + kLossNotificationPayloadLength;
53 }
54 
Create(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback callback) const55 bool LossNotification::Create(uint8_t* packet,
56                               size_t* index,
57                               size_t max_length,
58                               PacketReadyCallback callback) const {
59   while (*index + BlockLength() > max_length) {
60     if (!OnBufferFull(packet, index, callback))
61       return false;
62   }
63 
64   const size_t index_end = *index + BlockLength();
65 
66   // Note: `index` updated by the function below.
67   CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet,
68                index);
69 
70   CreateCommonFeedback(packet + *index);
71   *index += kCommonFeedbackLength;
72 
73   ByteWriter<uint32_t>::WriteBigEndian(packet + *index, kUniqueIdentifier);
74   *index += sizeof(uint32_t);
75 
76   ByteWriter<uint16_t>::WriteBigEndian(packet + *index, last_decoded_);
77   *index += sizeof(uint16_t);
78 
79   const uint16_t last_received_delta = last_received_ - last_decoded_;
80   RTC_DCHECK_LE(last_received_delta, 0x7fff);
81   const uint16_t last_received_delta_and_decodability =
82       (last_received_delta << 1) | (decodability_flag_ ? 0x0001 : 0x0000);
83 
84   ByteWriter<uint16_t>::WriteBigEndian(packet + *index,
85                                        last_received_delta_and_decodability);
86   *index += sizeof(uint16_t);
87 
88   RTC_DCHECK_EQ(index_end, *index);
89   return true;
90 }
91 
Parse(const CommonHeader & packet)92 bool LossNotification::Parse(const CommonHeader& packet) {
93   RTC_DCHECK_EQ(packet.type(), kPacketType);
94   RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType);
95 
96   if (packet.payload_size_bytes() <
97       kCommonFeedbackLength + kLossNotificationPayloadLength) {
98     return false;
99   }
100 
101   const uint8_t* const payload = packet.payload();
102 
103   if (ByteReader<uint32_t>::ReadBigEndian(&payload[8]) != kUniqueIdentifier) {
104     return false;
105   }
106 
107   ParseCommonFeedback(payload);
108 
109   last_decoded_ = ByteReader<uint16_t>::ReadBigEndian(&payload[12]);
110 
111   const uint16_t last_received_delta_and_decodability =
112       ByteReader<uint16_t>::ReadBigEndian(&payload[14]);
113   last_received_ = last_decoded_ + (last_received_delta_and_decodability >> 1);
114   decodability_flag_ = (last_received_delta_and_decodability & 0x0001);
115 
116   return true;
117 }
118 
Set(uint16_t last_decoded,uint16_t last_received,bool decodability_flag)119 bool LossNotification::Set(uint16_t last_decoded,
120                            uint16_t last_received,
121                            bool decodability_flag) {
122   const uint16_t delta = last_received - last_decoded;
123   if (delta > 0x7fff) {
124     return false;
125   }
126   last_received_ = last_received;
127   last_decoded_ = last_decoded;
128   decodability_flag_ = decodability_flag;
129   return true;
130 }
131 
132 }  // namespace rtcp
133 }  // namespace webrtc
134