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