| /* |
| * 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(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 |