1 // Copyright 2013 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/rtcp/rtcp_sender.h" 6 7 #include <stdint.h> 8 9 #include <algorithm> 10 #include <vector> 11 12 #include "base/big_endian.h" 13 #include "base/logging.h" 14 #include "media/cast/cast_environment.h" 15 #include "media/cast/rtcp/rtcp_defines.h" 16 #include "media/cast/rtcp/rtcp_utility.h" 17 #include "media/cast/transport/cast_transport_defines.h" 18 #include "media/cast/transport/pacing/paced_sender.h" 19 20 namespace media { 21 namespace cast { 22 namespace { 23 24 // Max delta is 4095 milliseconds because we need to be able to encode it in 25 // 12 bits. 26 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff); 27 28 uint16 MergeEventTypeAndTimestampForWireFormat( 29 const CastLoggingEvent& event, 30 const base::TimeDelta& time_delta) { 31 int64 time_delta_ms = time_delta.InMilliseconds(); 32 33 DCHECK_GE(time_delta_ms, 0); 34 DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs); 35 36 uint16 time_delta_12_bits = 37 static_cast<uint16>(time_delta_ms & kMaxWireFormatTimeDeltaMs); 38 39 uint16 event_type_4_bits = ConvertEventTypeToWireFormat(event); 40 DCHECK(event_type_4_bits); 41 DCHECK(~(event_type_4_bits & 0xfff0)); 42 return (event_type_4_bits << 12) | time_delta_12_bits; 43 } 44 45 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs, 46 const RtcpReceiverEventLogMessage& rhs) { 47 return lhs.event_timestamp < rhs.event_timestamp; 48 } 49 50 void AddReceiverLog( 51 const RtcpReceiverLogMessage& redundancy_receiver_log_message, 52 RtcpReceiverLogMessage* receiver_log_message, 53 size_t* remaining_space, 54 size_t* number_of_frames, 55 size_t* total_number_of_messages_to_send) { 56 RtcpReceiverLogMessage::const_iterator it = 57 redundancy_receiver_log_message.begin(); 58 while (it != redundancy_receiver_log_message.end() && 59 *remaining_space >= 60 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { 61 receiver_log_message->push_front(*it); 62 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / 63 kRtcpReceiverEventLogSize; 64 RtcpReceiverEventLogMessages& event_log_messages = 65 receiver_log_message->front().event_log_messages_; 66 if (num_event_logs < event_log_messages.size()) 67 event_log_messages.resize(num_event_logs); 68 69 *remaining_space -= kRtcpReceiverFrameLogSize + 70 event_log_messages.size() * kRtcpReceiverEventLogSize; 71 ++*number_of_frames; 72 *total_number_of_messages_to_send += event_log_messages.size(); 73 ++it; 74 } 75 } 76 77 // A class to build a string representing the NACK list in Cast message. 78 // 79 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame 80 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of 81 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is 82 // completely missing will show as "26:65535". 83 class NackStringBuilder { 84 public: 85 NackStringBuilder() 86 : frame_count_(0), 87 packet_count_(0), 88 last_frame_id_(-1), 89 last_packet_id_(-1), 90 contiguous_sequence_(false) {} 91 ~NackStringBuilder() {} 92 93 bool Empty() const { return frame_count_ == 0; } 94 95 void PushFrame(int frame_id) { 96 DCHECK_GE(frame_id, 0); 97 if (frame_count_ > 0) { 98 if (frame_id == last_frame_id_) { 99 return; 100 } 101 if (contiguous_sequence_) { 102 stream_ << "-" << last_packet_id_; 103 } 104 stream_ << ", "; 105 } 106 stream_ << frame_id; 107 last_frame_id_ = frame_id; 108 packet_count_ = 0; 109 contiguous_sequence_ = false; 110 ++frame_count_; 111 } 112 113 void PushPacket(int packet_id) { 114 DCHECK_GE(last_frame_id_, 0); 115 DCHECK_GE(packet_id, 0); 116 if (packet_count_ == 0) { 117 stream_ << ":" << packet_id; 118 } else if (packet_id == last_packet_id_ + 1) { 119 contiguous_sequence_ = true; 120 } else { 121 if (contiguous_sequence_) { 122 stream_ << "-" << last_packet_id_; 123 contiguous_sequence_ = false; 124 } 125 stream_ << "," << packet_id; 126 } 127 ++packet_count_; 128 last_packet_id_ = packet_id; 129 } 130 131 std::string GetString() { 132 if (contiguous_sequence_) { 133 stream_ << "-" << last_packet_id_; 134 contiguous_sequence_ = false; 135 } 136 return stream_.str(); 137 } 138 139 private: 140 std::ostringstream stream_; 141 int frame_count_; 142 int packet_count_; 143 int last_frame_id_; 144 int last_packet_id_; 145 bool contiguous_sequence_; 146 }; 147 } // namespace 148 149 // TODO(mikhal): This is only used by the receiver. Consider renaming. 150 RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment, 151 transport::PacedPacketSender* outgoing_transport, 152 uint32 sending_ssrc, 153 const std::string& c_name) 154 : ssrc_(sending_ssrc), 155 c_name_(c_name), 156 transport_(outgoing_transport), 157 cast_environment_(cast_environment) { 158 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; 159 } 160 161 RtcpSender::~RtcpSender() {} 162 163 void RtcpSender::SendRtcpFromRtpReceiver( 164 uint32 packet_type_flags, 165 const transport::RtcpReportBlock* report_block, 166 const RtcpReceiverReferenceTimeReport* rrtr, 167 const RtcpCastMessage* cast_message, 168 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, 169 uint16 target_delay_ms) { 170 if (packet_type_flags & transport::kRtcpSr || 171 packet_type_flags & transport::kRtcpDlrr || 172 packet_type_flags & transport::kRtcpSenderLog) { 173 NOTREACHED() << "Invalid argument"; 174 } 175 if (packet_type_flags & transport::kRtcpPli || 176 packet_type_flags & transport::kRtcpRpsi || 177 packet_type_flags & transport::kRtcpRemb || 178 packet_type_flags & transport::kRtcpNack) { 179 // Implement these for webrtc interop. 180 NOTIMPLEMENTED(); 181 } 182 transport::PacketRef packet(new base::RefCountedData<Packet>); 183 packet->data.reserve(kMaxIpPacketSize); 184 185 if (packet_type_flags & transport::kRtcpRr) { 186 BuildRR(report_block, &packet->data); 187 if (!c_name_.empty()) { 188 BuildSdec(&packet->data); 189 } 190 } 191 if (packet_type_flags & transport::kRtcpBye) { 192 BuildBye(&packet->data); 193 } 194 if (packet_type_flags & transport::kRtcpRrtr) { 195 DCHECK(rrtr) << "Invalid argument"; 196 BuildRrtr(rrtr, &packet->data); 197 } 198 if (packet_type_flags & transport::kRtcpCast) { 199 DCHECK(cast_message) << "Invalid argument"; 200 BuildCast(cast_message, target_delay_ms, &packet->data); 201 } 202 if (packet_type_flags & transport::kRtcpReceiverLog) { 203 DCHECK(rtcp_events) << "Invalid argument"; 204 BuildReceiverLog(*rtcp_events, &packet->data); 205 } 206 207 if (packet->data.empty()) 208 return; // Sanity don't send empty packets. 209 210 transport_->SendRtcpPacket(ssrc_, packet); 211 } 212 213 void RtcpSender::BuildRR(const transport::RtcpReportBlock* report_block, 214 Packet* packet) const { 215 size_t start_size = packet->size(); 216 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space"; 217 if (start_size + 32 > kMaxIpPacketSize) 218 return; 219 220 uint16 number_of_rows = (report_block) ? 7 : 1; 221 packet->resize(start_size + 8); 222 223 base::BigEndianWriter big_endian_writer( 224 reinterpret_cast<char*>(&((*packet)[start_size])), 8); 225 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); 226 big_endian_writer.WriteU8(transport::kPacketTypeReceiverReport); 227 big_endian_writer.WriteU16(number_of_rows); 228 big_endian_writer.WriteU32(ssrc_); 229 230 if (report_block) { 231 AddReportBlocks(*report_block, packet); // Adds 24 bytes. 232 } 233 } 234 235 void RtcpSender::AddReportBlocks(const transport::RtcpReportBlock& report_block, 236 Packet* packet) const { 237 size_t start_size = packet->size(); 238 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; 239 if (start_size + 24 > kMaxIpPacketSize) 240 return; 241 242 packet->resize(start_size + 24); 243 244 base::BigEndianWriter big_endian_writer( 245 reinterpret_cast<char*>(&((*packet)[start_size])), 24); 246 big_endian_writer.WriteU32(report_block.media_ssrc); 247 big_endian_writer.WriteU8(report_block.fraction_lost); 248 big_endian_writer.WriteU8(report_block.cumulative_lost >> 16); 249 big_endian_writer.WriteU8(report_block.cumulative_lost >> 8); 250 big_endian_writer.WriteU8(report_block.cumulative_lost); 251 252 // Extended highest seq_no, contain the highest sequence number received. 253 big_endian_writer.WriteU32(report_block.extended_high_sequence_number); 254 big_endian_writer.WriteU32(report_block.jitter); 255 256 // Last SR timestamp; our NTP time when we received the last report. 257 // This is the value that we read from the send report packet not when we 258 // received it. 259 big_endian_writer.WriteU32(report_block.last_sr); 260 261 // Delay since last received report, time since we received the report. 262 big_endian_writer.WriteU32(report_block.delay_since_last_sr); 263 } 264 265 void RtcpSender::BuildSdec(Packet* packet) const { 266 size_t start_size = packet->size(); 267 DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize) 268 << "Not enough buffer space"; 269 if (start_size + 12 > kMaxIpPacketSize) 270 return; 271 272 // SDES Source Description. 273 packet->resize(start_size + 10); 274 275 base::BigEndianWriter big_endian_writer( 276 reinterpret_cast<char*>(&((*packet)[start_size])), 10); 277 // We always need to add one SDES CNAME. 278 big_endian_writer.WriteU8(0x80 + 1); 279 big_endian_writer.WriteU8(transport::kPacketTypeSdes); 280 281 // Handle SDES length later on. 282 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3; 283 big_endian_writer.WriteU16(0); 284 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 285 big_endian_writer.WriteU8(1); // CNAME = 1 286 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length())); 287 288 size_t sdes_length = 10 + c_name_.length(); 289 packet->insert( 290 packet->end(), c_name_.c_str(), c_name_.c_str() + c_name_.length()); 291 292 size_t padding = 0; 293 294 // We must have a zero field even if we have an even multiple of 4 bytes. 295 if ((packet->size() % 4) == 0) { 296 padding++; 297 packet->push_back(0); 298 } 299 while ((packet->size() % 4) != 0) { 300 padding++; 301 packet->push_back(0); 302 } 303 sdes_length += padding; 304 305 // In 32-bit words minus one and we don't count the header. 306 uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1); 307 (*packet)[sdes_length_position] = buffer_length; 308 } 309 310 void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const { 311 size_t start_size = packet->size(); 312 DCHECK_LT(start_size + 12, kMaxIpPacketSize) << "Not enough buffer space"; 313 if (start_size + 12 > kMaxIpPacketSize) 314 return; 315 316 packet->resize(start_size + 12); 317 318 base::BigEndianWriter big_endian_writer( 319 reinterpret_cast<char*>(&((*packet)[start_size])), 12); 320 uint8 FMT = 1; // Picture loss indicator. 321 big_endian_writer.WriteU8(0x80 + FMT); 322 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific); 323 big_endian_writer.WriteU16(2); // Used fixed length of 2. 324 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 325 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC. 326 } 327 328 /* 329 0 1 2 3 330 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 331 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 332 | PB |0| Payload Type| Native Rpsi bit string | 333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 334 | defined per codec ... | Padding (0) | 335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 336 */ 337 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const { 338 size_t start_size = packet->size(); 339 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; 340 if (start_size + 24 > kMaxIpPacketSize) 341 return; 342 343 packet->resize(start_size + 24); 344 345 base::BigEndianWriter big_endian_writer( 346 reinterpret_cast<char*>(&((*packet)[start_size])), 24); 347 uint8 FMT = 3; // Reference Picture Selection Indication. 348 big_endian_writer.WriteU8(0x80 + FMT); 349 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific); 350 351 // Calculate length. 352 uint32 bits_required = 7; 353 uint8 bytes_required = 1; 354 while ((rpsi->picture_id >> bits_required) > 0) { 355 bits_required += 7; 356 bytes_required++; 357 } 358 uint8 size = 3; 359 if (bytes_required > 6) { 360 size = 5; 361 } else if (bytes_required > 2) { 362 size = 4; 363 } 364 big_endian_writer.WriteU8(0); 365 big_endian_writer.WriteU8(size); 366 big_endian_writer.WriteU32(ssrc_); 367 big_endian_writer.WriteU32(rpsi->remote_ssrc); 368 369 uint8 padding_bytes = 4 - ((2 + bytes_required) % 4); 370 if (padding_bytes == 4) { 371 padding_bytes = 0; 372 } 373 // Add padding length in bits, padding can be 0, 8, 16 or 24. 374 big_endian_writer.WriteU8(padding_bytes * 8); 375 big_endian_writer.WriteU8(rpsi->payload_type); 376 377 // Add picture ID. 378 for (int i = bytes_required - 1; i > 0; i--) { 379 big_endian_writer.WriteU8(0x80 | 380 static_cast<uint8>(rpsi->picture_id >> (i * 7))); 381 } 382 // Add last byte of picture ID. 383 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f)); 384 385 // Add padding. 386 for (int j = 0; j < padding_bytes; ++j) { 387 big_endian_writer.WriteU8(0); 388 } 389 } 390 391 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const { 392 size_t start_size = packet->size(); 393 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size(); 394 DCHECK_LT(start_size + remb_size, kMaxIpPacketSize) 395 << "Not enough buffer space"; 396 if (start_size + remb_size > kMaxIpPacketSize) 397 return; 398 399 packet->resize(start_size + remb_size); 400 401 base::BigEndianWriter big_endian_writer( 402 reinterpret_cast<char*>(&((*packet)[start_size])), remb_size); 403 404 // Add application layer feedback. 405 uint8 FMT = 15; 406 big_endian_writer.WriteU8(0x80 + FMT); 407 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific); 408 big_endian_writer.WriteU8(0); 409 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4)); 410 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 411 big_endian_writer.WriteU32(0); // Remote SSRC must be 0. 412 big_endian_writer.WriteU32(kRemb); 413 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size())); 414 415 // 6 bit exponent and a 18 bit mantissa. 416 uint8 bitrate_exponent; 417 uint32 bitrate_mantissa; 418 BitrateToRembExponentBitrate( 419 remb->remb_bitrate, &bitrate_exponent, &bitrate_mantissa); 420 421 big_endian_writer.WriteU8(static_cast<uint8>( 422 (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03))); 423 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8)); 424 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa)); 425 426 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin(); 427 for (; it != remb->remb_ssrcs.end(); ++it) { 428 big_endian_writer.WriteU32(*it); 429 } 430 } 431 432 void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const { 433 size_t start_size = packet->size(); 434 DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space"; 435 if (start_size + 16 > kMaxIpPacketSize) 436 return; 437 438 packet->resize(start_size + 16); 439 440 base::BigEndianWriter big_endian_writer( 441 reinterpret_cast<char*>(&((*packet)[start_size])), 16); 442 443 uint8 FMT = 1; 444 big_endian_writer.WriteU8(0x80 + FMT); 445 big_endian_writer.WriteU8(transport::kPacketTypeGenericRtpFeedback); 446 big_endian_writer.WriteU8(0); 447 size_t nack_size_pos = start_size + 3; 448 big_endian_writer.WriteU8(3); 449 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 450 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC. 451 452 // Build NACK bitmasks and write them to the Rtcp message. 453 // The nack list should be sorted and not contain duplicates. 454 size_t number_of_nack_fields = 0; 455 size_t max_number_of_nack_fields = std::min<size_t>( 456 kRtcpMaxNackFields, (kMaxIpPacketSize - packet->size()) / 4); 457 458 std::list<uint16>::const_iterator it = nack->nack_list.begin(); 459 while (it != nack->nack_list.end() && 460 number_of_nack_fields < max_number_of_nack_fields) { 461 uint16 nack_sequence_number = *it; 462 uint16 bitmask = 0; 463 ++it; 464 while (it != nack->nack_list.end()) { 465 int shift = static_cast<uint16>(*it - nack_sequence_number) - 1; 466 if (shift >= 0 && shift <= 15) { 467 bitmask |= (1 << shift); 468 ++it; 469 } else { 470 break; 471 } 472 } 473 // Write the sequence number and the bitmask to the packet. 474 start_size = packet->size(); 475 DCHECK_LT(start_size + 4, kMaxIpPacketSize) << "Not enough buffer space"; 476 if (start_size + 4 > kMaxIpPacketSize) 477 return; 478 479 packet->resize(start_size + 4); 480 base::BigEndianWriter big_endian_nack_writer( 481 reinterpret_cast<char*>(&((*packet)[start_size])), 4); 482 big_endian_nack_writer.WriteU16(nack_sequence_number); 483 big_endian_nack_writer.WriteU16(bitmask); 484 number_of_nack_fields++; 485 } 486 DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields); 487 (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields); 488 } 489 490 void RtcpSender::BuildBye(Packet* packet) const { 491 size_t start_size = packet->size(); 492 DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space"; 493 if (start_size + 8 > kMaxIpPacketSize) 494 return; 495 496 packet->resize(start_size + 8); 497 498 base::BigEndianWriter big_endian_writer( 499 reinterpret_cast<char*>(&((*packet)[start_size])), 8); 500 big_endian_writer.WriteU8(0x80 + 1); 501 big_endian_writer.WriteU8(transport::kPacketTypeBye); 502 big_endian_writer.WriteU16(1); // Length. 503 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 504 } 505 506 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, 507 Packet* packet) const { 508 size_t start_size = packet->size(); 509 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; 510 if (start_size + 20 > kMaxIpPacketSize) 511 return; 512 513 packet->resize(start_size + 20); 514 515 base::BigEndianWriter big_endian_writer( 516 reinterpret_cast<char*>(&((*packet)[start_size])), 20); 517 518 big_endian_writer.WriteU8(0x80); 519 big_endian_writer.WriteU8(transport::kPacketTypeXr); 520 big_endian_writer.WriteU16(4); // Length. 521 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 522 big_endian_writer.WriteU8(4); // Add block type. 523 big_endian_writer.WriteU8(0); // Add reserved. 524 big_endian_writer.WriteU16(2); // Block length. 525 526 // Add the media (received RTP) SSRC. 527 big_endian_writer.WriteU32(rrtr->ntp_seconds); 528 big_endian_writer.WriteU32(rrtr->ntp_fraction); 529 } 530 531 void RtcpSender::BuildCast(const RtcpCastMessage* cast, 532 uint16 target_delay_ms, 533 Packet* packet) const { 534 size_t start_size = packet->size(); 535 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; 536 if (start_size + 20 > kMaxIpPacketSize) 537 return; 538 539 packet->resize(start_size + 20); 540 541 base::BigEndianWriter big_endian_writer( 542 reinterpret_cast<char*>(&((*packet)[start_size])), 20); 543 uint8 FMT = 15; // Application layer feedback. 544 big_endian_writer.WriteU8(0x80 + FMT); 545 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific); 546 big_endian_writer.WriteU8(0); 547 size_t cast_size_pos = start_size + 3; // Save length position. 548 big_endian_writer.WriteU8(4); 549 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 550 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC. 551 big_endian_writer.WriteU32(kCast); 552 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_)); 553 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. 554 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. 555 big_endian_writer.WriteU16(target_delay_ms); 556 557 size_t number_of_loss_fields = 0; 558 size_t max_number_of_loss_fields = std::min<size_t>( 559 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4); 560 561 MissingFramesAndPacketsMap::const_iterator frame_it = 562 cast->missing_frames_and_packets_.begin(); 563 564 NackStringBuilder nack_string_builder; 565 for (; frame_it != cast->missing_frames_and_packets_.end() && 566 number_of_loss_fields < max_number_of_loss_fields; 567 ++frame_it) { 568 nack_string_builder.PushFrame(frame_it->first); 569 // Iterate through all frames with missing packets. 570 if (frame_it->second.empty()) { 571 // Special case all packets in a frame is missing. 572 start_size = packet->size(); 573 packet->resize(start_size + 4); 574 base::BigEndianWriter big_endian_nack_writer( 575 reinterpret_cast<char*>(&((*packet)[start_size])), 4); 576 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); 577 big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost); 578 big_endian_nack_writer.WriteU8(0); 579 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost); 580 ++number_of_loss_fields; 581 } else { 582 PacketIdSet::const_iterator packet_it = frame_it->second.begin(); 583 while (packet_it != frame_it->second.end()) { 584 uint16 packet_id = *packet_it; 585 586 start_size = packet->size(); 587 packet->resize(start_size + 4); 588 base::BigEndianWriter big_endian_nack_writer( 589 reinterpret_cast<char*>(&((*packet)[start_size])), 4); 590 591 // Write frame and packet id to buffer before calculating bitmask. 592 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); 593 big_endian_nack_writer.WriteU16(packet_id); 594 nack_string_builder.PushPacket(packet_id); 595 596 uint8 bitmask = 0; 597 ++packet_it; 598 while (packet_it != frame_it->second.end()) { 599 int shift = static_cast<uint8>(*packet_it - packet_id) - 1; 600 if (shift >= 0 && shift <= 7) { 601 nack_string_builder.PushPacket(*packet_it); 602 bitmask |= (1 << shift); 603 ++packet_it; 604 } else { 605 break; 606 } 607 } 608 big_endian_nack_writer.WriteU8(bitmask); 609 ++number_of_loss_fields; 610 } 611 } 612 } 613 VLOG_IF(1, !nack_string_builder.Empty()) 614 << "SSRC: " << cast->media_ssrc_ 615 << ", ACK: " << cast->ack_frame_id_ 616 << ", NACK: " << nack_string_builder.GetString(); 617 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); 618 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); 619 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); 620 } 621 622 void RtcpSender::BuildReceiverLog( 623 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, 624 Packet* packet) { 625 const size_t packet_start_size = packet->size(); 626 size_t number_of_frames = 0; 627 size_t total_number_of_messages_to_send = 0; 628 size_t rtcp_log_size = 0; 629 RtcpReceiverLogMessage receiver_log_message; 630 631 if (!BuildRtcpReceiverLogMessage(rtcp_events, 632 packet_start_size, 633 &receiver_log_message, 634 &number_of_frames, 635 &total_number_of_messages_to_send, 636 &rtcp_log_size)) { 637 return; 638 } 639 packet->resize(packet_start_size + rtcp_log_size); 640 641 base::BigEndianWriter big_endian_writer( 642 reinterpret_cast<char*>(&((*packet)[packet_start_size])), rtcp_log_size); 643 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype); 644 big_endian_writer.WriteU8(transport::kPacketTypeApplicationDefined); 645 big_endian_writer.WriteU16(static_cast<uint16>( 646 2 + 2 * number_of_frames + total_number_of_messages_to_send)); 647 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. 648 big_endian_writer.WriteU32(kCast); 649 650 while (!receiver_log_message.empty() && 651 total_number_of_messages_to_send > 0) { 652 RtcpReceiverFrameLogMessage& frame_log_messages( 653 receiver_log_message.front()); 654 655 // Add our frame header. 656 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_); 657 size_t messages_in_frame = frame_log_messages.event_log_messages_.size(); 658 if (messages_in_frame > total_number_of_messages_to_send) { 659 // We are running out of space. 660 messages_in_frame = total_number_of_messages_to_send; 661 } 662 // Keep track of how many messages we have left to send. 663 total_number_of_messages_to_send -= messages_in_frame; 664 665 // On the wire format is number of messages - 1. 666 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1)); 667 668 base::TimeTicks event_timestamp_base = 669 frame_log_messages.event_log_messages_.front().event_timestamp; 670 uint32 base_timestamp_ms = 671 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); 672 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); 673 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); 674 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms)); 675 676 while (!frame_log_messages.event_log_messages_.empty() && 677 messages_in_frame > 0) { 678 const RtcpReceiverEventLogMessage& event_message = 679 frame_log_messages.event_log_messages_.front(); 680 uint16 event_type_and_timestamp_delta = 681 MergeEventTypeAndTimestampForWireFormat( 682 event_message.type, 683 event_message.event_timestamp - event_timestamp_base); 684 switch (event_message.type) { 685 case FRAME_ACK_SENT: 686 case FRAME_PLAYOUT: 687 case FRAME_DECODED: 688 big_endian_writer.WriteU16( 689 static_cast<uint16>(event_message.delay_delta.InMilliseconds())); 690 big_endian_writer.WriteU16(event_type_and_timestamp_delta); 691 break; 692 case PACKET_RECEIVED: 693 big_endian_writer.WriteU16(event_message.packet_id); 694 big_endian_writer.WriteU16(event_type_and_timestamp_delta); 695 break; 696 default: 697 NOTREACHED(); 698 } 699 messages_in_frame--; 700 frame_log_messages.event_log_messages_.pop_front(); 701 } 702 if (frame_log_messages.event_log_messages_.empty()) { 703 // We sent all messages on this frame; pop the frame header. 704 receiver_log_message.pop_front(); 705 } 706 } 707 DCHECK_EQ(total_number_of_messages_to_send, 0u); 708 } 709 710 bool RtcpSender::BuildRtcpReceiverLogMessage( 711 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, 712 size_t start_size, 713 RtcpReceiverLogMessage* receiver_log_message, 714 size_t* number_of_frames, 715 size_t* total_number_of_messages_to_send, 716 size_t* rtcp_log_size) { 717 size_t remaining_space = 718 std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size); 719 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + 720 kRtcpReceiverEventLogSize) { 721 return false; 722 } 723 724 // We use this to do event timestamp sorting and truncating for events of 725 // a single frame. 726 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; 727 728 // Account for the RTCP header for an application-defined packet. 729 remaining_space -= kRtcpCastLogHeaderSize; 730 731 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = 732 rtcp_events.rbegin(); 733 734 while (rit != rtcp_events.rend() && 735 remaining_space >= 736 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { 737 const RtpTimestamp rtp_timestamp = rit->first; 738 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); 739 remaining_space -= kRtcpReceiverFrameLogSize; 740 ++*number_of_frames; 741 742 // Get all events of a single frame. 743 sorted_log_messages.clear(); 744 do { 745 RtcpReceiverEventLogMessage event_log_message; 746 event_log_message.type = rit->second.type; 747 event_log_message.event_timestamp = rit->second.timestamp; 748 event_log_message.delay_delta = rit->second.delay_delta; 749 event_log_message.packet_id = rit->second.packet_id; 750 sorted_log_messages.push_back(event_log_message); 751 ++rit; 752 } while (rit != rtcp_events.rend() && rit->first == rtp_timestamp); 753 754 std::sort(sorted_log_messages.begin(), 755 sorted_log_messages.end(), 756 &EventTimestampLessThan); 757 758 // From |sorted_log_messages|, only take events that are no greater than 759 // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events 760 // older than that cannot be encoded over the wire. 761 std::vector<RtcpReceiverEventLogMessage>::reverse_iterator sorted_rit = 762 sorted_log_messages.rbegin(); 763 base::TimeTicks first_event_timestamp = sorted_rit->event_timestamp; 764 size_t events_in_frame = 0; 765 while (sorted_rit != sorted_log_messages.rend() && 766 events_in_frame < kRtcpMaxReceiverLogMessages && 767 remaining_space >= kRtcpReceiverEventLogSize) { 768 base::TimeDelta delta(first_event_timestamp - 769 sorted_rit->event_timestamp); 770 if (delta.InMilliseconds() > kMaxWireFormatTimeDeltaMs) 771 break; 772 frame_log.event_log_messages_.push_front(*sorted_rit); 773 ++events_in_frame; 774 ++*total_number_of_messages_to_send; 775 remaining_space -= kRtcpReceiverEventLogSize; 776 ++sorted_rit; 777 } 778 779 receiver_log_message->push_front(frame_log); 780 } 781 782 rtcp_events_history_.push_front(*receiver_log_message); 783 784 // We don't try to match RTP timestamps of redundancy frame logs with those 785 // from the newest set (which would save the space of an extra RTP timestamp 786 // over the wire). Unless the redundancy frame logs are very recent, it's 787 // unlikely there will be a match anyway. 788 if (rtcp_events_history_.size() > kFirstRedundancyOffset) { 789 // Add first redundnacy messages, if enough space remaining 790 AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset], 791 receiver_log_message, 792 &remaining_space, 793 number_of_frames, 794 total_number_of_messages_to_send); 795 } 796 797 if (rtcp_events_history_.size() > kSecondRedundancyOffset) { 798 // Add second redundancy messages, if enough space remaining 799 AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset], 800 receiver_log_message, 801 &remaining_space, 802 number_of_frames, 803 total_number_of_messages_to_send); 804 } 805 806 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { 807 rtcp_events_history_.pop_back(); 808 } 809 810 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); 811 812 *rtcp_log_size = 813 kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize + 814 *total_number_of_messages_to_send * kRtcpReceiverEventLogSize; 815 DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size) 816 << "Not enough buffer space."; 817 818 VLOG(3) << "number of frames: " << *number_of_frames; 819 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; 820 VLOG(3) << "rtcp log size: " << *rtcp_log_size; 821 return *number_of_frames > 0; 822 } 823 824 } // namespace cast 825 } // namespace media 826