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