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