| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |