1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/cast/net/rtcp/rtcp_builder.h"
6 
7 #include <stdint.h>
8 
9 #include <algorithm>
10 #include <vector>
11 
12 #include "base/logging.h"
13 #include "media/cast/net/rtcp/rtcp_utility.h"
14 
15 namespace media {
16 namespace cast {
17 namespace {
18 
19 // Max delta is 4095 milliseconds because we need to be able to encode it in
20 // 12 bits.
21 const int64_t kMaxWireFormatTimeDeltaMs = INT64_C(0xfff);
22 
MergeEventTypeAndTimestampForWireFormat(const CastLoggingEvent & event,const base::TimeDelta & time_delta)23 uint16_t MergeEventTypeAndTimestampForWireFormat(
24     const CastLoggingEvent& event,
25     const base::TimeDelta& time_delta) {
26   int64_t time_delta_ms = time_delta.InMilliseconds();
27 
28   DCHECK_GE(time_delta_ms, 0);
29   DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs);
30 
31   uint16_t time_delta_12_bits =
32       static_cast<uint16_t>(time_delta_ms & kMaxWireFormatTimeDeltaMs);
33 
34   uint16_t event_type_4_bits = ConvertEventTypeToWireFormat(event);
35   DCHECK(event_type_4_bits);
36   DCHECK(~(event_type_4_bits & 0xfff0));
37   return (event_type_4_bits << 12) | time_delta_12_bits;
38 }
39 
EventTimestampLessThan(const RtcpReceiverEventLogMessage & lhs,const RtcpReceiverEventLogMessage & rhs)40 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs,
41                             const RtcpReceiverEventLogMessage& rhs) {
42   return lhs.event_timestamp < rhs.event_timestamp;
43 }
44 
45 // A class to build a string representing the NACK list in Cast message.
46 //
47 // The string will look like "F23:3-6 F25:1,5-6", meaning packets 3 to 6 in
48 // frame 23 are being NACK'ed (i.e. they are missing from the receiver's point
49 // of view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
50 // completely missing will show as "F26:65535".
51 class NackStringBuilder {
52  public:
NackStringBuilder()53   NackStringBuilder()
54       : frame_count_(0),
55         packet_count_(0),
56         last_packet_id_(-1),
57         contiguous_sequence_(false) {}
58   ~NackStringBuilder() = default;
59 
Empty() const60   bool Empty() const { return frame_count_ == 0; }
61 
PushFrame(FrameId frame_id)62   void PushFrame(FrameId frame_id) {
63     DCHECK(!frame_id.is_null());
64     if (frame_count_ > 0) {
65       if (frame_id == last_frame_id_) {
66         return;
67       }
68       if (contiguous_sequence_) {
69         stream_ << "-" << last_packet_id_;
70       }
71       stream_ << ", ";
72     }
73     stream_ << frame_id;
74     last_frame_id_ = frame_id;
75     packet_count_ = 0;
76     contiguous_sequence_ = false;
77     ++frame_count_;
78   }
79 
PushPacket(int packet_id)80   void PushPacket(int packet_id) {
81     DCHECK(!last_frame_id_.is_null());
82     DCHECK_GE(packet_id, 0);
83     if (packet_count_ == 0) {
84       stream_ << ":" << packet_id;
85     } else if (packet_id == last_packet_id_ + 1) {
86       contiguous_sequence_ = true;
87     } else {
88       if (contiguous_sequence_) {
89         stream_ << "-" << last_packet_id_;
90         contiguous_sequence_ = false;
91       }
92       stream_ << "," << packet_id;
93     }
94     ++packet_count_;
95     last_packet_id_ = packet_id;
96   }
97 
GetString()98   std::string GetString() {
99     if (contiguous_sequence_) {
100       stream_ << "-" << last_packet_id_;
101       contiguous_sequence_ = false;
102     }
103     return stream_.str();
104   }
105 
106  private:
107   std::ostringstream stream_;
108   int frame_count_;
109   int packet_count_;
110   FrameId last_frame_id_;
111   int last_packet_id_;
112   bool contiguous_sequence_;
113 };
114 }  // namespace
115 
RtcpBuilder(uint32_t sending_ssrc)116 RtcpBuilder::RtcpBuilder(uint32_t sending_ssrc)
117     : writer_(NULL, 0), local_ssrc_(sending_ssrc), ptr_of_length_(NULL) {}
118 
119 RtcpBuilder::~RtcpBuilder() = default;
120 
PatchLengthField()121 void RtcpBuilder::PatchLengthField() {
122   if (ptr_of_length_) {
123     // Back-patch the packet length. The client must have taken
124     // care of proper padding to 32-bit words.
125     int this_packet_length = (writer_.ptr() - ptr_of_length_ - 2);
126     DCHECK_EQ(0, this_packet_length % 4)
127         << "Packets must be a multiple of 32 bits long";
128     *ptr_of_length_ = this_packet_length >> 10;
129     *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF;
130     ptr_of_length_ = NULL;
131   }
132 }
133 
134 // Set the 5-bit value in the 1st byte of the header
135 // and the payload type. Set aside room for the length field,
136 // and make provision for back-patching it.
AddRtcpHeader(RtcpPacketFields payload,int format_or_count)137 void RtcpBuilder::AddRtcpHeader(RtcpPacketFields payload, int format_or_count) {
138   PatchLengthField();
139   writer_.WriteU8(0x80 | (format_or_count & 0x1F));
140   writer_.WriteU8(payload);
141   ptr_of_length_ = writer_.ptr();
142 
143   // Initialize length to "clearly illegal".
144   writer_.WriteU16(0xDEAD);
145 }
146 
Start()147 void RtcpBuilder::Start() {
148   packet_ = new base::RefCountedData<Packet>;
149   packet_->data.resize(kMaxIpPacketSize);
150   writer_ = base::BigEndianWriter(
151       reinterpret_cast<char*>(&(packet_->data[0])), kMaxIpPacketSize);
152 }
153 
Finish()154 PacketRef RtcpBuilder::Finish() {
155   PatchLengthField();
156   packet_->data.resize(kMaxIpPacketSize - writer_.remaining());
157   writer_ = base::BigEndianWriter(NULL, 0);
158   PacketRef ret = packet_;
159   packet_.reset();
160   return ret;
161 }
162 
BuildRtcpFromSender(const RtcpSenderInfo & sender_info)163 PacketRef RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo& sender_info) {
164   Start();
165   AddSR(sender_info);
166   return Finish();
167 }
168 
AddRR(const RtcpReportBlock * report_block)169 void RtcpBuilder::AddRR(const RtcpReportBlock* report_block) {
170   AddRtcpHeader(kPacketTypeReceiverReport, report_block ? 1 : 0);
171   writer_.WriteU32(local_ssrc_);
172   if (report_block) {
173     AddReportBlocks(*report_block);  // Adds 24 bytes.
174   }
175 }
176 
AddReportBlocks(const RtcpReportBlock & report_block)177 void RtcpBuilder::AddReportBlocks(const RtcpReportBlock& report_block) {
178   writer_.WriteU32(report_block.media_ssrc);
179   writer_.WriteU8(report_block.fraction_lost);
180   writer_.WriteU8(report_block.cumulative_lost >> 16);
181   writer_.WriteU8(report_block.cumulative_lost >> 8);
182   writer_.WriteU8(report_block.cumulative_lost);
183 
184   // Extended highest seq_no, contain the highest sequence number received.
185   writer_.WriteU32(report_block.extended_high_sequence_number);
186   writer_.WriteU32(report_block.jitter);
187 
188   // Last SR timestamp; our NTP time when we received the last report.
189   // This is the value that we read from the send report packet not when we
190   // received it.
191   writer_.WriteU32(report_block.last_sr);
192 
193   // Delay since last received report, time since we received the report.
194   writer_.WriteU32(report_block.delay_since_last_sr);
195 }
196 
AddRrtr(const RtcpReceiverReferenceTimeReport & rrtr)197 void RtcpBuilder::AddRrtr(const RtcpReceiverReferenceTimeReport& rrtr) {
198   AddRtcpHeader(kPacketTypeXr, 0);
199   writer_.WriteU32(local_ssrc_);  // Add our own SSRC.
200   writer_.WriteU8(4);       // Add block type.
201   writer_.WriteU8(0);       // Add reserved.
202   writer_.WriteU16(2);      // Block length.
203 
204   // Add the media (received RTP) SSRC.
205   writer_.WriteU32(rrtr.ntp_seconds);
206   writer_.WriteU32(rrtr.ntp_fraction);
207 }
208 
AddPli(const RtcpPliMessage & pli_message)209 void RtcpBuilder::AddPli(const RtcpPliMessage& pli_message) {
210   AddRtcpHeader(kPacketTypePayloadSpecific, 1);
211   writer_.WriteU32(local_ssrc_);
212   writer_.WriteU32(pli_message.remote_ssrc);
213 }
214 
AddCast(const RtcpCastMessage & cast,base::TimeDelta target_delay)215 void RtcpBuilder::AddCast(const RtcpCastMessage& cast,
216                           base::TimeDelta target_delay) {
217   // See RTC 4585 Section 6.4 for application specific feedback messages.
218   AddRtcpHeader(kPacketTypePayloadSpecific, 15);
219   writer_.WriteU32(local_ssrc_);      // Add our own SSRC.
220   writer_.WriteU32(cast.remote_ssrc);  // Remote SSRC.
221   writer_.WriteU32(kCast);
222   writer_.WriteU8(cast.ack_frame_id.lower_8_bits());
223   uint8_t* cast_loss_field_pos = reinterpret_cast<uint8_t*>(writer_.ptr());
224   writer_.WriteU8(0);  // Overwritten with number_of_loss_fields.
225   DCHECK_LE(target_delay.InMilliseconds(),
226             std::numeric_limits<uint16_t>::max());
227   writer_.WriteU16(target_delay.InMilliseconds());
228 
229   size_t number_of_loss_fields = 0;
230   size_t max_number_of_loss_fields = std::min<size_t>(
231       kRtcpMaxCastLossFields, writer_.remaining() / 4);
232 
233   auto frame_it = cast.missing_frames_and_packets.begin();
234 
235   NackStringBuilder nack_string_builder;
236   for (; frame_it != cast.missing_frames_and_packets.end() &&
237          number_of_loss_fields < max_number_of_loss_fields;
238        ++frame_it) {
239     nack_string_builder.PushFrame(frame_it->first);
240     // Iterate through all frames with missing packets.
241     if (frame_it->second.empty()) {
242       // Special case all packets in a frame is missing.
243       writer_.WriteU8(frame_it->first.lower_8_bits());
244       writer_.WriteU16(kRtcpCastAllPacketsLost);
245       writer_.WriteU8(0);
246       nack_string_builder.PushPacket(kRtcpCastAllPacketsLost);
247       ++number_of_loss_fields;
248     } else {
249       auto packet_it = frame_it->second.begin();
250       while (packet_it != frame_it->second.end()) {
251         uint16_t packet_id = *packet_it;
252         // Write frame and packet id to buffer before calculating bitmask.
253         writer_.WriteU8(frame_it->first.lower_8_bits());
254         writer_.WriteU16(packet_id);
255         nack_string_builder.PushPacket(packet_id);
256 
257         uint8_t bitmask = 0;
258         ++packet_it;
259         while (packet_it != frame_it->second.end()) {
260           int shift = static_cast<uint8_t>(*packet_it - packet_id) - 1;
261           if (shift >= 0 && shift <= 7) {
262             nack_string_builder.PushPacket(*packet_it);
263             bitmask |= (1 << shift);
264             ++packet_it;
265           } else {
266             break;
267           }
268         }
269         writer_.WriteU8(bitmask);
270         ++number_of_loss_fields;
271       }
272     }
273   }
274   VLOG_IF(1, !nack_string_builder.Empty())
275       << "SSRC: " << cast.remote_ssrc << ", ACK: " << cast.ack_frame_id
276       << ", NACK: " << nack_string_builder.GetString();
277   DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields);
278   *cast_loss_field_pos = static_cast<uint8_t>(number_of_loss_fields);
279 }
280 
AddSR(const RtcpSenderInfo & sender_info)281 void RtcpBuilder::AddSR(const RtcpSenderInfo& sender_info) {
282   AddRtcpHeader(kPacketTypeSenderReport, 0);
283   writer_.WriteU32(local_ssrc_);
284   writer_.WriteU32(sender_info.ntp_seconds);
285   writer_.WriteU32(sender_info.ntp_fraction);
286   writer_.WriteU32(sender_info.rtp_timestamp.lower_32_bits());
287   writer_.WriteU32(sender_info.send_packet_count);
288   writer_.WriteU32(static_cast<uint32_t>(sender_info.send_octet_count));
289 }
290 
291 /*
292    0                   1                   2                   3
293    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
294   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295   |V=2|P|reserved |   PT=XR=207   |             length            |
296   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
297   |                              SSRC                             |
298   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
299   |     BT=5      |   reserved    |         block length          |
300   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
301   |                 SSRC1 (SSRC of first receiver)               | sub-
302   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
303   |                         last RR (LRR)                         |   1
304   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305   |                   delay since last RR (DLRR)                  |
306   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
307 */
AddDlrrRb(const RtcpDlrrReportBlock & dlrr)308 void RtcpBuilder::AddDlrrRb(const RtcpDlrrReportBlock& dlrr) {
309   AddRtcpHeader(kPacketTypeXr, 0);
310   writer_.WriteU32(local_ssrc_);  // Add our own SSRC.
311   writer_.WriteU8(5);  // Add block type.
312   writer_.WriteU8(0);  // Add reserved.
313   writer_.WriteU16(3);  // Block length.
314   writer_.WriteU32(local_ssrc_);  // Add the media (received RTP) SSRC.
315   writer_.WriteU32(dlrr.last_rr);
316   writer_.WriteU32(dlrr.delay_since_last_rr);
317 }
318 
AddReceiverLog(const ReceiverRtcpEventSubscriber::RtcpEvents & rtcp_events)319 void RtcpBuilder::AddReceiverLog(
320     const ReceiverRtcpEventSubscriber::RtcpEvents& rtcp_events) {
321   size_t total_number_of_messages_to_send = 0;
322   RtcpReceiverLogMessage receiver_log_message;
323 
324   if (!GetRtcpReceiverLogMessage(rtcp_events,
325                                  &receiver_log_message,
326                                  &total_number_of_messages_to_send)) {
327     return;
328   }
329 
330   AddRtcpHeader(kPacketTypeApplicationDefined, kReceiverLogSubtype);
331   writer_.WriteU32(local_ssrc_);  // Add our own SSRC.
332   writer_.WriteU32(kCast);
333 
334   while (!receiver_log_message.empty() &&
335          total_number_of_messages_to_send > 0) {
336     RtcpReceiverFrameLogMessage& frame_log_messages(
337         receiver_log_message.front());
338 
339     // Add our frame header.
340     writer_.WriteU32(frame_log_messages.rtp_timestamp_.lower_32_bits());
341     size_t messages_in_frame = frame_log_messages.event_log_messages_.size();
342     if (messages_in_frame > total_number_of_messages_to_send) {
343       // We are running out of space.
344       messages_in_frame = total_number_of_messages_to_send;
345     }
346     // Keep track of how many messages we have left to send.
347     total_number_of_messages_to_send -= messages_in_frame;
348 
349     // On the wire format is number of messages - 1.
350     writer_.WriteU8(static_cast<uint8_t>(messages_in_frame - 1));
351 
352     base::TimeTicks event_timestamp_base =
353         frame_log_messages.event_log_messages_.front().event_timestamp;
354     uint32_t base_timestamp_ms =
355         (event_timestamp_base - base::TimeTicks()).InMilliseconds();
356     writer_.WriteU8(static_cast<uint8_t>(base_timestamp_ms >> 16));
357     writer_.WriteU8(static_cast<uint8_t>(base_timestamp_ms >> 8));
358     writer_.WriteU8(static_cast<uint8_t>(base_timestamp_ms));
359 
360     while (!frame_log_messages.event_log_messages_.empty() &&
361            messages_in_frame > 0) {
362       const RtcpReceiverEventLogMessage& event_message =
363           frame_log_messages.event_log_messages_.front();
364       uint16_t event_type_and_timestamp_delta =
365           MergeEventTypeAndTimestampForWireFormat(
366               event_message.type,
367               event_message.event_timestamp - event_timestamp_base);
368       switch (event_message.type) {
369         case FRAME_ACK_SENT:
370         case FRAME_PLAYOUT:
371         case FRAME_DECODED:
372           writer_.WriteU16(static_cast<uint16_t>(
373               event_message.delay_delta.InMilliseconds()));
374           writer_.WriteU16(event_type_and_timestamp_delta);
375           break;
376         case PACKET_RECEIVED:
377           writer_.WriteU16(event_message.packet_id);
378           writer_.WriteU16(event_type_and_timestamp_delta);
379           break;
380         default:
381           NOTREACHED();
382       }
383       messages_in_frame--;
384       frame_log_messages.event_log_messages_.pop_front();
385     }
386     if (frame_log_messages.event_log_messages_.empty()) {
387       // We sent all messages on this frame; pop the frame header.
388       receiver_log_message.pop_front();
389     }
390   }
391   DCHECK_EQ(total_number_of_messages_to_send, 0u);
392 }
393 
GetRtcpReceiverLogMessage(const ReceiverRtcpEventSubscriber::RtcpEvents & rtcp_events,RtcpReceiverLogMessage * receiver_log_message,size_t * total_number_of_messages_to_send)394 bool RtcpBuilder::GetRtcpReceiverLogMessage(
395     const ReceiverRtcpEventSubscriber::RtcpEvents& rtcp_events,
396     RtcpReceiverLogMessage* receiver_log_message,
397     size_t* total_number_of_messages_to_send) {
398   size_t number_of_frames = 0;
399   size_t remaining_space = writer_.remaining();
400   if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
401                             kRtcpReceiverEventLogSize) {
402     return false;
403   }
404 
405   // We use this to do event timestamp sorting and truncating for events of
406   // a single frame.
407   std::vector<RtcpReceiverEventLogMessage> sorted_log_messages;
408 
409   // Account for the RTCP header for an application-defined packet.
410   remaining_space -= kRtcpCastLogHeaderSize;
411 
412   auto rit = rtcp_events.rbegin();
413 
414   while (rit != rtcp_events.rend() &&
415          remaining_space >=
416              kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
417     const RtpTimeTicks rtp_timestamp = rit->first;
418     RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
419     remaining_space -= kRtcpReceiverFrameLogSize;
420     ++number_of_frames;
421 
422     // Get all events of a single frame.
423     sorted_log_messages.clear();
424     do {
425       RtcpReceiverEventLogMessage event_log_message;
426       event_log_message.type = rit->second.type;
427       event_log_message.event_timestamp = rit->second.timestamp;
428       event_log_message.delay_delta = rit->second.delay_delta;
429       event_log_message.packet_id = rit->second.packet_id;
430       sorted_log_messages.push_back(event_log_message);
431       ++rit;
432     } while (rit != rtcp_events.rend() && rit->first == rtp_timestamp);
433 
434     std::sort(sorted_log_messages.begin(),
435               sorted_log_messages.end(),
436               &EventTimestampLessThan);
437 
438     // From |sorted_log_messages|, only take events that are no greater than
439     // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events
440     // older than that cannot be encoded over the wire.
441     auto sorted_rit = sorted_log_messages.rbegin();
442     base::TimeTicks first_event_timestamp = sorted_rit->event_timestamp;
443     size_t events_in_frame = 0;
444     while (sorted_rit != sorted_log_messages.rend() &&
445            events_in_frame < kRtcpMaxReceiverLogMessages &&
446            remaining_space >= kRtcpReceiverEventLogSize) {
447       base::TimeDelta delta(first_event_timestamp -
448                             sorted_rit->event_timestamp);
449       if (delta.InMilliseconds() > kMaxWireFormatTimeDeltaMs)
450         break;
451       frame_log.event_log_messages_.push_front(*sorted_rit);
452       ++events_in_frame;
453       ++*total_number_of_messages_to_send;
454       remaining_space -= kRtcpReceiverEventLogSize;
455       ++sorted_rit;
456     }
457 
458     receiver_log_message->push_front(frame_log);
459   }
460 
461   VLOG(3) << "number of frames: " << number_of_frames;
462   VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send;
463   return number_of_frames > 0;
464 }
465 
466 }  // namespace cast
467 }  // namespace media
468