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