1a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap/* 2a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * 4a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * Use of this source code is governed by a BSD-style license 5a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * that can be found in the LICENSE file in the root of the source 6a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * tree. An additional intellectual property rights grant can be found 7a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * in the file PATENTS. All contributing project authors may 8a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap * be found in the AUTHORS file in the root of the source tree. 9a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap */ 10a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 11a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" 12a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 13a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include <algorithm> 14a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 15a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include "webrtc/base/checks.h" 16a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include "webrtc/base/logging.h" 17a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 18a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 19a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapusing webrtc::RTCPUtility::RtcpCommonHeader; 20a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 21a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapnamespace webrtc { 22a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapnamespace rtcp { 23a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 24a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// RFC 4585: Feedback format. 25a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 26a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// Common packet format: 27a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 28a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 0 1 2 3 29a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 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 30a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// |V=2|P| FMT | PT | length | 32a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 33a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 0 | SSRC of packet sender | 34a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 35a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 4 | SSRC of media source | 36a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 37a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// : Feedback Control Information (FCI) : 38a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// : : 39a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 40a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// Generic NACK (RFC 4585). 41a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 42a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// FCI: 43a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 0 1 2 3 44a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// 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 45a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// | PID | BLP | 47a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapbool Nack::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { 49a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(header.packet_type == kPacketType); 50a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(header.count_or_format == kFeedbackMessageType); 51a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 52a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap if (header.payload_size_bytes < kCommonFeedbackLength + kNackItemLength) { 53a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap LOG(LS_WARNING) << "Payload length " << header.payload_size_bytes 54a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap << " is too small for a Nack."; 55a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap return false; 56a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 57a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t nack_items = 58a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap (header.payload_size_bytes - kCommonFeedbackLength) / kNackItemLength; 59a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 60a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap ParseCommonFeedback(payload); 61a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap const uint8_t* next_nack = payload + kCommonFeedbackLength; 62a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 63a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packet_ids_.clear(); 64a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packed_.resize(nack_items); 65a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap for (size_t index = 0; index < nack_items; ++index) { 66a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packed_[index].first_pid = ByteReader<uint16_t>::ReadBigEndian(next_nack); 67a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packed_[index].bitmask = ByteReader<uint16_t>::ReadBigEndian(next_nack + 2); 68a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap next_nack += kNackItemLength; 69a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 70a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap Unpack(); 71a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 72a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap return true; 73a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 74a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 75a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapbool Nack::Create(uint8_t* packet, 76a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t* index, 77a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t max_length, 78a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RtcpPacket::PacketReadyCallback* callback) const { 79a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(!packed_.empty()); 80a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap // If nack list can't fit in packet, try to fragment. 81a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t nack_index = 0; 82a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap const size_t kCommonFbFmtLength = kHeaderLength + kCommonFeedbackLength; 83a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap do { 84a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t bytes_left_in_buffer = max_length - *index; 85a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap if (bytes_left_in_buffer < kCommonFbFmtLength + kNackItemLength) { 86a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap if (!OnBufferFull(packet, index, callback)) 87a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap return false; 88a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap continue; 89a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 90a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t num_nack_fields = 91a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap std::min((bytes_left_in_buffer - kCommonFbFmtLength) / kNackItemLength, 92a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packed_.size() - nack_index); 93a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 94a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t size_bytes = 95a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap (num_nack_fields * kNackItemLength) + kCommonFbFmtLength; 96a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t header_length = ((size_bytes + 3) / 4) - 1; // As 32bit words - 1 97a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap CreateHeader(kFeedbackMessageType, kPacketType, header_length, packet, 98a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap index); 99a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap CreateCommonFeedback(packet + *index); 100a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap *index += kCommonFeedbackLength; 101a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap size_t end_index = nack_index + num_nack_fields; 102a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap for (; nack_index < end_index; ++nack_index) { 103a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap const auto& item = packed_[nack_index]; 104a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap ByteWriter<uint16_t>::WriteBigEndian(packet + *index + 0, item.first_pid); 105a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap ByteWriter<uint16_t>::WriteBigEndian(packet + *index + 2, item.bitmask); 106a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap *index += kNackItemLength; 107a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 108a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK_LE(*index, max_length); 109a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } while (nack_index < packed_.size()); 110a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 111a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap return true; 112a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 113a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 114a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapsize_t Nack::BlockLength() const { 115a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap return (packed_.size() * kNackItemLength) + kCommonFeedbackLength + 116a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap kHeaderLength; 117a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 118a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 119a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapvoid Nack::WithList(const uint16_t* nack_list, size_t length) { 120a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(nack_list); 121a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(packet_ids_.empty()); 122a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(packed_.empty()); 123a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packet_ids_.assign(nack_list, nack_list + length); 124a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap Pack(); 125a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 126a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 127a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapvoid Nack::Pack() { 128a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(!packet_ids_.empty()); 129a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(packed_.empty()); 130a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap auto it = packet_ids_.begin(); 131a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap const auto end = packet_ids_.end(); 132a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap while (it != end) { 133a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap PackedNack item; 134a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap item.first_pid = *it++; 135a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap // Bitmask specifies losses in any of the 16 packets following the pid. 136a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap item.bitmask = 0; 137a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap while (it != end) { 138a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap uint16_t shift = static_cast<uint16_t>(*it - item.first_pid - 1); 139a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap if (shift <= 15) { 140a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap item.bitmask |= (1 << shift); 141a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap ++it; 142a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } else { 143a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap break; 144a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 145a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 146a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packed_.push_back(item); 147a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 148a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 149a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 150a8890a57a5d03f942924ff61d3c62244f2bdab10danilchapvoid Nack::Unpack() { 151a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(packet_ids_.empty()); 152a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap RTC_DCHECK(!packed_.empty()); 153a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap for (const PackedNack& item : packed_) { 154a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packet_ids_.push_back(item.first_pid); 155a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap uint16_t pid = item.first_pid + 1; 156a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap for (uint16_t bitmask = item.bitmask; bitmask != 0; bitmask >>= 1, ++pid) 157a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap if (bitmask & 1) 158a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap packet_ids_.push_back(pid); 159a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap } 160a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} 161a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap 162a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} // namespace rtcp 163a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap} // namespace webrtc 164