/* * 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::WriteBigEndian(packet + *index, kUniqueIdentifier); *index += sizeof(uint32_t); ByteWriter::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::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::ReadBigEndian(&payload[8]) != kUniqueIdentifier) { return false; } ParseCommonFeedback(payload); last_decoded_ = ByteReader::ReadBigEndian(&payload[12]); const uint16_t last_received_delta_and_decodability = ByteReader::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