diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc new file mode 100644 index 0000000000..0817846f95 --- /dev/null +++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtcp_packet/loss_notification.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h" + +#include "modules/rtp_rtcp/source/byte_io.h" +#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" + +namespace webrtc { +namespace rtcp { + +// Loss Notification +// ----------------- +// 0 1 2 3 +// 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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT=15 | PT=206 | length | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// 0 | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | Unique identifier 'L' 'N' 'T' 'F' | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 12 | Last Decoded Sequence Number | Last Received SeqNum Delta |D| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +LossNotification::LossNotification() + : last_decoded_(0), last_received_(0), decodability_flag_(false) {} + +LossNotification::LossNotification(uint16_t last_decoded, + uint16_t last_received, + bool decodability_flag) + : last_decoded_(last_decoded), + last_received_(last_received), + decodability_flag_(decodability_flag) {} + +LossNotification::LossNotification(const LossNotification& rhs) = default; + +LossNotification::~LossNotification() = default; + +size_t LossNotification::BlockLength() const { + return kHeaderLength + kCommonFeedbackLength + kLossNotificationPayloadLength; +} + +bool LossNotification::Create(uint8_t* packet, + size_t* index, + size_t max_length, + PacketReadyCallback callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + + const size_t index_end = *index + BlockLength(); + + // Note: `index` updated by the function below. + CreateHeader(Psfb::kAfbMessageType, kPacketType, HeaderLength(), packet, + index); + + CreateCommonFeedback(packet + *index); + *index += kCommonFeedbackLength; + + ByteWriter<uint32_t>::WriteBigEndian(packet + *index, kUniqueIdentifier); + *index += sizeof(uint32_t); + + ByteWriter<uint16_t>::WriteBigEndian(packet + *index, last_decoded_); + *index += sizeof(uint16_t); + + const uint16_t last_received_delta = last_received_ - last_decoded_; + RTC_DCHECK_LE(last_received_delta, 0x7fff); + const uint16_t last_received_delta_and_decodability = + (last_received_delta << 1) | (decodability_flag_ ? 0x0001 : 0x0000); + + ByteWriter<uint16_t>::WriteBigEndian(packet + *index, + last_received_delta_and_decodability); + *index += sizeof(uint16_t); + + RTC_DCHECK_EQ(index_end, *index); + return true; +} + +bool LossNotification::Parse(const CommonHeader& packet) { + RTC_DCHECK_EQ(packet.type(), kPacketType); + RTC_DCHECK_EQ(packet.fmt(), Psfb::kAfbMessageType); + + if (packet.payload_size_bytes() < + kCommonFeedbackLength + kLossNotificationPayloadLength) { + return false; + } + + const uint8_t* const payload = packet.payload(); + + if (ByteReader<uint32_t>::ReadBigEndian(&payload[8]) != kUniqueIdentifier) { + return false; + } + + ParseCommonFeedback(payload); + + last_decoded_ = ByteReader<uint16_t>::ReadBigEndian(&payload[12]); + + const uint16_t last_received_delta_and_decodability = + ByteReader<uint16_t>::ReadBigEndian(&payload[14]); + last_received_ = last_decoded_ + (last_received_delta_and_decodability >> 1); + decodability_flag_ = (last_received_delta_and_decodability & 0x0001); + + return true; +} + +bool LossNotification::Set(uint16_t last_decoded, + uint16_t last_received, + bool decodability_flag) { + const uint16_t delta = last_received - last_decoded; + if (delta > 0x7fff) { + return false; + } + last_received_ = last_received; + last_decoded_ = last_decoded; + decodability_flag_ = decodability_flag; + return true; +} + +} // namespace rtcp +} // namespace webrtc |