| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/cast/net/rtcp/rtcp_sender.h" | 5 #include "media/cast/net/rtcp/rtcp_builder.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/big_endian.h" | |
| 13 #include "base/logging.h" | 12 #include "base/logging.h" |
| 14 #include "media/cast/net/cast_transport_defines.h" | 13 #include "media/cast/net/cast_transport_defines.h" |
| 15 #include "media/cast/net/pacing/paced_sender.h" | |
| 16 #include "media/cast/net/rtcp/rtcp_defines.h" | 14 #include "media/cast/net/rtcp/rtcp_defines.h" |
| 17 #include "media/cast/net/rtcp/rtcp_utility.h" | 15 #include "media/cast/net/rtcp/rtcp_utility.h" |
| 18 | 16 |
| 19 namespace media { | 17 namespace media { |
| 20 namespace cast { | 18 namespace cast { |
| 21 namespace { | 19 namespace { |
| 22 | 20 |
| 23 // Max delta is 4095 milliseconds because we need to be able to encode it in | 21 // Max delta is 4095 milliseconds because we need to be able to encode it in |
| 24 // 12 bits. | 22 // 12 bits. |
| 25 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff); | 23 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 receiver_log_message->push_front(*it); | 58 receiver_log_message->push_front(*it); |
| 61 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / | 59 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / |
| 62 kRtcpReceiverEventLogSize; | 60 kRtcpReceiverEventLogSize; |
| 63 RtcpReceiverEventLogMessages& event_log_messages = | 61 RtcpReceiverEventLogMessages& event_log_messages = |
| 64 receiver_log_message->front().event_log_messages_; | 62 receiver_log_message->front().event_log_messages_; |
| 65 if (num_event_logs < event_log_messages.size()) | 63 if (num_event_logs < event_log_messages.size()) |
| 66 event_log_messages.resize(num_event_logs); | 64 event_log_messages.resize(num_event_logs); |
| 67 | 65 |
| 68 *remaining_space -= kRtcpReceiverFrameLogSize + | 66 *remaining_space -= kRtcpReceiverFrameLogSize + |
| 69 event_log_messages.size() * kRtcpReceiverEventLogSize; | 67 event_log_messages.size() * kRtcpReceiverEventLogSize; |
| 70 ++*number_of_frames; | 68 ++number_of_frames; |
| 71 *total_number_of_messages_to_send += event_log_messages.size(); | 69 *total_number_of_messages_to_send += event_log_messages.size(); |
| 72 ++it; | 70 ++it; |
| 73 } | 71 } |
| 74 } | 72 } |
| 75 | 73 |
| 76 // A class to build a string representing the NACK list in Cast message. | 74 // A class to build a string representing the NACK list in Cast message. |
| 77 // | 75 // |
| 78 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame | 76 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame |
| 79 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of | 77 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of |
| 80 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is | 78 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 private: | 136 private: |
| 139 std::ostringstream stream_; | 137 std::ostringstream stream_; |
| 140 int frame_count_; | 138 int frame_count_; |
| 141 int packet_count_; | 139 int packet_count_; |
| 142 int last_frame_id_; | 140 int last_frame_id_; |
| 143 int last_packet_id_; | 141 int last_packet_id_; |
| 144 bool contiguous_sequence_; | 142 bool contiguous_sequence_; |
| 145 }; | 143 }; |
| 146 } // namespace | 144 } // namespace |
| 147 | 145 |
| 148 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, | 146 RtcpBuilder::RtcpBuilder(uint32 sending_ssrc) |
| 149 uint32 sending_ssrc) | 147 : writer_(NULL, 0), |
| 150 : ssrc_(sending_ssrc), | 148 ssrc_(sending_ssrc), |
| 151 transport_(outgoing_transport) { | 149 ptr_of_length_(NULL) { |
| 152 } | 150 } |
| 153 | 151 |
| 154 RtcpSender::~RtcpSender() {} | 152 RtcpBuilder::~RtcpBuilder() {} |
| 155 | 153 |
| 156 void RtcpSender::SendRtcpFromRtpReceiver( | 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( |
| 157 const RtcpReportBlock* report_block, | 197 const RtcpReportBlock* report_block, |
| 158 const RtcpReceiverReferenceTimeReport* rrtr, | 198 const RtcpReceiverReferenceTimeReport* rrtr, |
| 159 const RtcpCastMessage* cast_message, | 199 const RtcpCastMessage* cast_message, |
| 160 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, | 200 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, |
| 161 base::TimeDelta target_delay) { | 201 base::TimeDelta target_delay) { |
| 162 PacketRef packet(new base::RefCountedData<Packet>); | 202 Start(); |
| 163 packet->data.reserve(kMaxIpPacketSize); | 203 |
| 164 if (report_block) | 204 if (report_block) |
| 165 BuildRR(report_block, &packet->data); | 205 BuildRR(report_block); |
| 166 if (rrtr) | 206 if (rrtr) |
| 167 BuildRrtr(rrtr, &packet->data); | 207 BuildRrtr(rrtr); |
| 168 if (cast_message) | 208 if (cast_message) |
| 169 BuildCast(cast_message, target_delay, &packet->data); | 209 BuildCast(cast_message, target_delay); |
| 170 if (rtcp_events) | 210 if (rtcp_events) |
| 171 BuildReceiverLog(*rtcp_events, &packet->data); | 211 BuildReceiverLog(*rtcp_events); |
| 172 | 212 |
| 173 if (packet->data.empty()) { | 213 return Finish(); |
| 174 NOTREACHED() << "Empty packet."; | |
| 175 return; // Sanity don't send empty packets. | |
| 176 } | |
| 177 | |
| 178 transport_->SendRtcpPacket(ssrc_, packet); | |
| 179 } | 214 } |
| 180 | 215 |
| 181 void RtcpSender::SendRtcpFromRtpSender( | 216 PacketRef RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo& sender_info) { |
| 182 const RtcpSenderInfo& sender_info) { | 217 Start(); |
| 183 PacketRef packet(new base::RefCountedData<Packet>); | 218 BuildSR(sender_info); |
| 184 packet->data.reserve(kMaxIpPacketSize); | 219 return Finish(); |
| 185 BuildSR(sender_info, &packet->data); | |
| 186 | |
| 187 if (packet->data.empty()) { | |
| 188 NOTREACHED() << "Empty packet."; | |
| 189 return; // Sanity - don't send empty packets. | |
| 190 } | |
| 191 | |
| 192 transport_->SendRtcpPacket(ssrc_, packet); | |
| 193 } | 220 } |
| 194 | 221 |
| 195 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, | 222 void RtcpBuilder::BuildRR(const RtcpReportBlock* report_block) { |
| 196 Packet* packet) const { | 223 AddRtcpHeader(kPacketTypeReceiverReport, report_block ? 1 : 0); |
| 197 size_t start_size = packet->size(); | 224 writer_.WriteU32(ssrc_); |
| 198 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space"; | |
| 199 if (start_size + 32 > kMaxIpPacketSize) | |
| 200 return; | |
| 201 | |
| 202 uint16 number_of_rows = (report_block) ? 7 : 1; | |
| 203 packet->resize(start_size + 8); | |
| 204 | |
| 205 base::BigEndianWriter big_endian_writer( | |
| 206 reinterpret_cast<char*>(&((*packet)[start_size])), 8); | |
| 207 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); | |
| 208 big_endian_writer.WriteU8(kPacketTypeReceiverReport); | |
| 209 big_endian_writer.WriteU16(number_of_rows); | |
| 210 big_endian_writer.WriteU32(ssrc_); | |
| 211 | |
| 212 if (report_block) { | 225 if (report_block) { |
| 213 AddReportBlocks(*report_block, packet); // Adds 24 bytes. | 226 AddReportBlocks(*report_block); // Adds 24 bytes. |
| 214 } | 227 } |
| 215 } | 228 } |
| 216 | 229 |
| 217 void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block, | 230 void RtcpBuilder::AddReportBlocks(const RtcpReportBlock& report_block) { |
| 218 Packet* packet) const { | 231 writer_.WriteU32(report_block.media_ssrc); |
| 219 size_t start_size = packet->size(); | 232 writer_.WriteU8(report_block.fraction_lost); |
| 220 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; | 233 writer_.WriteU8(report_block.cumulative_lost >> 16); |
| 221 if (start_size + 24 > kMaxIpPacketSize) | 234 writer_.WriteU8(report_block.cumulative_lost >> 8); |
| 222 return; | 235 writer_.WriteU8(report_block.cumulative_lost); |
| 223 | |
| 224 packet->resize(start_size + 24); | |
| 225 | |
| 226 base::BigEndianWriter big_endian_writer( | |
| 227 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | |
| 228 big_endian_writer.WriteU32(report_block.media_ssrc); | |
| 229 big_endian_writer.WriteU8(report_block.fraction_lost); | |
| 230 big_endian_writer.WriteU8(report_block.cumulative_lost >> 16); | |
| 231 big_endian_writer.WriteU8(report_block.cumulative_lost >> 8); | |
| 232 big_endian_writer.WriteU8(report_block.cumulative_lost); | |
| 233 | 236 |
| 234 // Extended highest seq_no, contain the highest sequence number received. | 237 // Extended highest seq_no, contain the highest sequence number received. |
| 235 big_endian_writer.WriteU32(report_block.extended_high_sequence_number); | 238 writer_.WriteU32(report_block.extended_high_sequence_number); |
| 236 big_endian_writer.WriteU32(report_block.jitter); | 239 writer_.WriteU32(report_block.jitter); |
| 237 | 240 |
| 238 // Last SR timestamp; our NTP time when we received the last report. | 241 // Last SR timestamp; our NTP time when we received the last report. |
| 239 // This is the value that we read from the send report packet not when we | 242 // This is the value that we read from the send report packet not when we |
| 240 // received it. | 243 // received it. |
| 241 big_endian_writer.WriteU32(report_block.last_sr); | 244 writer_.WriteU32(report_block.last_sr); |
| 242 | 245 |
| 243 // Delay since last received report, time since we received the report. | 246 // Delay since last received report, time since we received the report. |
| 244 big_endian_writer.WriteU32(report_block.delay_since_last_sr); | 247 writer_.WriteU32(report_block.delay_since_last_sr); |
| 245 } | 248 } |
| 246 | 249 |
| 247 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, | 250 void RtcpBuilder::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr) { |
| 248 Packet* packet) const { | 251 AddRtcpHeader(kPacketTypeXr, 0); |
| 249 size_t start_size = packet->size(); | 252 writer_.WriteU32(ssrc_); // Add our own SSRC. |
| 250 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; | 253 writer_.WriteU8(4); // Add block type. |
| 251 if (start_size + 20 > kMaxIpPacketSize) | 254 writer_.WriteU8(0); // Add reserved. |
| 252 return; | 255 writer_.WriteU16(2); // Block length. |
| 253 | |
| 254 packet->resize(start_size + 20); | |
| 255 | |
| 256 base::BigEndianWriter big_endian_writer( | |
| 257 reinterpret_cast<char*>(&((*packet)[start_size])), 20); | |
| 258 | |
| 259 big_endian_writer.WriteU8(0x80); | |
| 260 big_endian_writer.WriteU8(kPacketTypeXr); | |
| 261 big_endian_writer.WriteU16(4); // Length. | |
| 262 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 263 big_endian_writer.WriteU8(4); // Add block type. | |
| 264 big_endian_writer.WriteU8(0); // Add reserved. | |
| 265 big_endian_writer.WriteU16(2); // Block length. | |
| 266 | 256 |
| 267 // Add the media (received RTP) SSRC. | 257 // Add the media (received RTP) SSRC. |
| 268 big_endian_writer.WriteU32(rrtr->ntp_seconds); | 258 writer_.WriteU32(rrtr->ntp_seconds); |
| 269 big_endian_writer.WriteU32(rrtr->ntp_fraction); | 259 writer_.WriteU32(rrtr->ntp_fraction); |
| 270 } | 260 } |
| 271 | 261 |
| 272 void RtcpSender::BuildCast(const RtcpCastMessage* cast, | 262 void RtcpBuilder::BuildCast(const RtcpCastMessage* cast, |
| 273 base::TimeDelta target_delay, | 263 base::TimeDelta target_delay) { |
| 274 Packet* packet) const { | 264 // See RTC 4585 Section 6.4 for application specific feedback messages. |
| 275 size_t start_size = packet->size(); | 265 AddRtcpHeader(kPacketTypePayloadSpecific, 15); |
| 276 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; | 266 writer_.WriteU32(ssrc_); // Add our own SSRC. |
| 277 if (start_size + 20 > kMaxIpPacketSize) | 267 writer_.WriteU32(cast->media_ssrc); // Remote SSRC. |
| 278 return; | 268 writer_.WriteU32(kCast); |
| 279 | 269 writer_.WriteU8(static_cast<uint8>(cast->ack_frame_id)); |
| 280 packet->resize(start_size + 20); | 270 uint8* cast_loss_field_pos = reinterpret_cast<uint8*>(writer_.ptr()); |
| 281 | 271 writer_.WriteU8(0); // Overwritten with number_of_loss_fields. |
| 282 base::BigEndianWriter big_endian_writer( | |
| 283 reinterpret_cast<char*>(&((*packet)[start_size])), 20); | |
| 284 uint8 FMT = 15; // Application layer feedback. | |
| 285 big_endian_writer.WriteU8(0x80 + FMT); | |
| 286 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | |
| 287 big_endian_writer.WriteU8(0); | |
| 288 size_t cast_size_pos = start_size + 3; // Save length position. | |
| 289 big_endian_writer.WriteU8(4); | |
| 290 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 291 big_endian_writer.WriteU32(cast->media_ssrc); // Remote SSRC. | |
| 292 big_endian_writer.WriteU32(kCast); | |
| 293 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id)); | |
| 294 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. | |
| 295 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. | |
| 296 DCHECK_LE(target_delay.InMilliseconds(), | 272 DCHECK_LE(target_delay.InMilliseconds(), |
| 297 std::numeric_limits<uint16_t>::max()); | 273 std::numeric_limits<uint16_t>::max()); |
| 298 big_endian_writer.WriteU16(target_delay.InMilliseconds()); | 274 writer_.WriteU16(target_delay.InMilliseconds()); |
| 299 | 275 |
| 300 size_t number_of_loss_fields = 0; | 276 size_t number_of_loss_fields = 0; |
| 301 size_t max_number_of_loss_fields = std::min<size_t>( | 277 size_t max_number_of_loss_fields = std::min<size_t>( |
| 302 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4); | 278 kRtcpMaxCastLossFields, writer_.remaining() / 4); |
| 303 | 279 |
| 304 MissingFramesAndPacketsMap::const_iterator frame_it = | 280 MissingFramesAndPacketsMap::const_iterator frame_it = |
| 305 cast->missing_frames_and_packets.begin(); | 281 cast->missing_frames_and_packets.begin(); |
| 306 | 282 |
| 307 NackStringBuilder nack_string_builder; | 283 NackStringBuilder nack_string_builder; |
| 308 for (; frame_it != cast->missing_frames_and_packets.end() && | 284 for (; frame_it != cast->missing_frames_and_packets.end() && |
| 309 number_of_loss_fields < max_number_of_loss_fields; | 285 number_of_loss_fields < max_number_of_loss_fields; |
| 310 ++frame_it) { | 286 ++frame_it) { |
| 311 nack_string_builder.PushFrame(frame_it->first); | 287 nack_string_builder.PushFrame(frame_it->first); |
| 312 // Iterate through all frames with missing packets. | 288 // Iterate through all frames with missing packets. |
| 313 if (frame_it->second.empty()) { | 289 if (frame_it->second.empty()) { |
| 314 // Special case all packets in a frame is missing. | 290 // Special case all packets in a frame is missing. |
| 315 start_size = packet->size(); | 291 writer_.WriteU8(static_cast<uint8>(frame_it->first)); |
| 316 packet->resize(start_size + 4); | 292 writer_.WriteU16(kRtcpCastAllPacketsLost); |
| 317 base::BigEndianWriter big_endian_nack_writer( | 293 writer_.WriteU8(0); |
| 318 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | |
| 319 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); | |
| 320 big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost); | |
| 321 big_endian_nack_writer.WriteU8(0); | |
| 322 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost); | 294 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost); |
| 323 ++number_of_loss_fields; | 295 ++number_of_loss_fields; |
| 324 } else { | 296 } else { |
| 325 PacketIdSet::const_iterator packet_it = frame_it->second.begin(); | 297 PacketIdSet::const_iterator packet_it = frame_it->second.begin(); |
| 326 while (packet_it != frame_it->second.end()) { | 298 while (packet_it != frame_it->second.end()) { |
| 327 uint16 packet_id = *packet_it; | 299 uint16 packet_id = *packet_it; |
| 328 | |
| 329 start_size = packet->size(); | |
| 330 packet->resize(start_size + 4); | |
| 331 base::BigEndianWriter big_endian_nack_writer( | |
| 332 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | |
| 333 | |
| 334 // Write frame and packet id to buffer before calculating bitmask. | 300 // Write frame and packet id to buffer before calculating bitmask. |
| 335 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); | 301 writer_.WriteU8(static_cast<uint8>(frame_it->first)); |
| 336 big_endian_nack_writer.WriteU16(packet_id); | 302 writer_.WriteU16(packet_id); |
| 337 nack_string_builder.PushPacket(packet_id); | 303 nack_string_builder.PushPacket(packet_id); |
| 338 | 304 |
| 339 uint8 bitmask = 0; | 305 uint8 bitmask = 0; |
| 340 ++packet_it; | 306 ++packet_it; |
| 341 while (packet_it != frame_it->second.end()) { | 307 while (packet_it != frame_it->second.end()) { |
| 342 int shift = static_cast<uint8>(*packet_it - packet_id) - 1; | 308 int shift = static_cast<uint8>(*packet_it - packet_id) - 1; |
| 343 if (shift >= 0 && shift <= 7) { | 309 if (shift >= 0 && shift <= 7) { |
| 344 nack_string_builder.PushPacket(*packet_it); | 310 nack_string_builder.PushPacket(*packet_it); |
| 345 bitmask |= (1 << shift); | 311 bitmask |= (1 << shift); |
| 346 ++packet_it; | 312 ++packet_it; |
| 347 } else { | 313 } else { |
| 348 break; | 314 break; |
| 349 } | 315 } |
| 350 } | 316 } |
| 351 big_endian_nack_writer.WriteU8(bitmask); | 317 writer_.WriteU8(bitmask); |
| 352 ++number_of_loss_fields; | 318 ++number_of_loss_fields; |
| 353 } | 319 } |
| 354 } | 320 } |
| 355 } | 321 } |
| 356 VLOG_IF(1, !nack_string_builder.Empty()) | 322 VLOG_IF(1, !nack_string_builder.Empty()) |
| 357 << "SSRC: " << cast->media_ssrc | 323 << "SSRC: " << cast->media_ssrc |
| 358 << ", ACK: " << cast->ack_frame_id | 324 << ", ACK: " << cast->ack_frame_id |
| 359 << ", NACK: " << nack_string_builder.GetString(); | 325 << ", NACK: " << nack_string_builder.GetString(); |
| 360 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); | 326 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); |
| 361 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); | 327 *cast_loss_field_pos = static_cast<uint8>(number_of_loss_fields); |
| 362 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); | |
| 363 } | 328 } |
| 364 | 329 |
| 365 void RtcpSender::BuildSR(const RtcpSenderInfo& sender_info, | 330 void RtcpBuilder::BuildSR(const RtcpSenderInfo& sender_info) { |
| 366 Packet* packet) const { | 331 AddRtcpHeader(kPacketTypeSenderReport, 0); |
| 367 // Sender report. | 332 writer_.WriteU32(ssrc_); |
| 368 size_t start_size = packet->size(); | 333 writer_.WriteU32(sender_info.ntp_seconds); |
| 369 if (start_size + 52 > kMaxIpPacketSize) { | 334 writer_.WriteU32(sender_info.ntp_fraction); |
| 370 DLOG(FATAL) << "Not enough buffer space"; | 335 writer_.WriteU32(sender_info.rtp_timestamp); |
| 371 return; | 336 writer_.WriteU32(sender_info.send_packet_count); |
| 372 } | 337 writer_.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); |
| 373 | |
| 374 uint16 number_of_rows = 6; | |
| 375 packet->resize(start_size + 28); | |
| 376 | |
| 377 base::BigEndianWriter big_endian_writer( | |
| 378 reinterpret_cast<char*>(&((*packet)[start_size])), 28); | |
| 379 big_endian_writer.WriteU8(0x80); | |
| 380 big_endian_writer.WriteU8(kPacketTypeSenderReport); | |
| 381 big_endian_writer.WriteU16(number_of_rows); | |
| 382 big_endian_writer.WriteU32(ssrc_); | |
| 383 big_endian_writer.WriteU32(sender_info.ntp_seconds); | |
| 384 big_endian_writer.WriteU32(sender_info.ntp_fraction); | |
| 385 big_endian_writer.WriteU32(sender_info.rtp_timestamp); | |
| 386 big_endian_writer.WriteU32(sender_info.send_packet_count); | |
| 387 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); | |
| 388 return; | |
| 389 } | 338 } |
| 390 | 339 |
| 391 /* | 340 /* |
| 392 0 1 2 3 | 341 0 1 2 3 |
| 393 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 | 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 |
| 394 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 395 |V=2|P|reserved | PT=XR=207 | length | | 344 |V=2|P|reserved | PT=XR=207 | length | |
| 396 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 345 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 397 | SSRC | | 346 | SSRC | |
| 398 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 347 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 399 | BT=5 | reserved | block length | | 348 | BT=5 | reserved | block length | |
| 400 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | 349 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| 401 | SSRC1 (SSRC of first receiver) | sub- | 350 | SSRC1 (SSRC of first receiver) | sub- |
| 402 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block | 351 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block |
| 403 | last RR (LRR) | 1 | 352 | last RR (LRR) | 1 |
| 404 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 405 | delay since last RR (DLRR) | | 354 | delay since last RR (DLRR) | |
| 406 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | 355 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| 407 */ | 356 */ |
| 408 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, | 357 void RtcpBuilder::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr) { |
| 409 Packet* packet) const { | 358 AddRtcpHeader(kPacketTypeXr, 0); |
| 410 size_t start_size = packet->size(); | 359 writer_.WriteU32(ssrc_); // Add our own SSRC. |
| 411 if (start_size + 24 > kMaxIpPacketSize) { | 360 writer_.WriteU8(5); // Add block type. |
| 412 DLOG(FATAL) << "Not enough buffer space"; | 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::BuildReceiverLog( |
| 369 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events) { |
| 370 size_t total_number_of_messages_to_send = 0; |
| 371 RtcpReceiverLogMessage receiver_log_message; |
| 372 |
| 373 if (!BuildRtcpReceiverLogMessage(rtcp_events, |
| 374 &receiver_log_message, |
| 375 &total_number_of_messages_to_send)) { |
| 413 return; | 376 return; |
| 414 } | 377 } |
| 415 | 378 |
| 416 packet->resize(start_size + 24); | 379 AddRtcpHeader(kPacketTypeApplicationDefined, kReceiverLogSubtype); |
| 417 | 380 writer_.WriteU32(ssrc_); // Add our own SSRC. |
| 418 base::BigEndianWriter big_endian_writer( | 381 writer_.WriteU32(kCast); |
| 419 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | |
| 420 big_endian_writer.WriteU8(0x80); | |
| 421 big_endian_writer.WriteU8(kPacketTypeXr); | |
| 422 big_endian_writer.WriteU16(5); // Length. | |
| 423 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 424 big_endian_writer.WriteU8(5); // Add block type. | |
| 425 big_endian_writer.WriteU8(0); // Add reserved. | |
| 426 big_endian_writer.WriteU16(3); // Block length. | |
| 427 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. | |
| 428 big_endian_writer.WriteU32(dlrr.last_rr); | |
| 429 big_endian_writer.WriteU32(dlrr.delay_since_last_rr); | |
| 430 return; | |
| 431 } | |
| 432 | |
| 433 void RtcpSender::BuildReceiverLog( | |
| 434 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, | |
| 435 Packet* packet) { | |
| 436 const size_t packet_start_size = packet->size(); | |
| 437 size_t number_of_frames = 0; | |
| 438 size_t total_number_of_messages_to_send = 0; | |
| 439 size_t rtcp_log_size = 0; | |
| 440 RtcpReceiverLogMessage receiver_log_message; | |
| 441 | |
| 442 if (!BuildRtcpReceiverLogMessage(rtcp_events, | |
| 443 packet_start_size, | |
| 444 &receiver_log_message, | |
| 445 &number_of_frames, | |
| 446 &total_number_of_messages_to_send, | |
| 447 &rtcp_log_size)) { | |
| 448 return; | |
| 449 } | |
| 450 packet->resize(packet_start_size + rtcp_log_size); | |
| 451 | |
| 452 base::BigEndianWriter big_endian_writer( | |
| 453 reinterpret_cast<char*>(&((*packet)[packet_start_size])), rtcp_log_size); | |
| 454 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype); | |
| 455 big_endian_writer.WriteU8(kPacketTypeApplicationDefined); | |
| 456 big_endian_writer.WriteU16(static_cast<uint16>( | |
| 457 2 + 2 * number_of_frames + total_number_of_messages_to_send)); | |
| 458 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 459 big_endian_writer.WriteU32(kCast); | |
| 460 | 382 |
| 461 while (!receiver_log_message.empty() && | 383 while (!receiver_log_message.empty() && |
| 462 total_number_of_messages_to_send > 0) { | 384 total_number_of_messages_to_send > 0) { |
| 463 RtcpReceiverFrameLogMessage& frame_log_messages( | 385 RtcpReceiverFrameLogMessage& frame_log_messages( |
| 464 receiver_log_message.front()); | 386 receiver_log_message.front()); |
| 465 | 387 |
| 466 // Add our frame header. | 388 // Add our frame header. |
| 467 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_); | 389 writer_.WriteU32(frame_log_messages.rtp_timestamp_); |
| 468 size_t messages_in_frame = frame_log_messages.event_log_messages_.size(); | 390 size_t messages_in_frame = frame_log_messages.event_log_messages_.size(); |
| 469 if (messages_in_frame > total_number_of_messages_to_send) { | 391 if (messages_in_frame > total_number_of_messages_to_send) { |
| 470 // We are running out of space. | 392 // We are running out of space. |
| 471 messages_in_frame = total_number_of_messages_to_send; | 393 messages_in_frame = total_number_of_messages_to_send; |
| 472 } | 394 } |
| 473 // Keep track of how many messages we have left to send. | 395 // Keep track of how many messages we have left to send. |
| 474 total_number_of_messages_to_send -= messages_in_frame; | 396 total_number_of_messages_to_send -= messages_in_frame; |
| 475 | 397 |
| 476 // On the wire format is number of messages - 1. | 398 // On the wire format is number of messages - 1. |
| 477 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1)); | 399 writer_.WriteU8(static_cast<uint8>(messages_in_frame - 1)); |
| 478 | 400 |
| 479 base::TimeTicks event_timestamp_base = | 401 base::TimeTicks event_timestamp_base = |
| 480 frame_log_messages.event_log_messages_.front().event_timestamp; | 402 frame_log_messages.event_log_messages_.front().event_timestamp; |
| 481 uint32 base_timestamp_ms = | 403 uint32 base_timestamp_ms = |
| 482 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); | 404 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); |
| 483 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); | 405 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); |
| 484 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); | 406 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); |
| 485 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms)); | 407 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms)); |
| 486 | 408 |
| 487 while (!frame_log_messages.event_log_messages_.empty() && | 409 while (!frame_log_messages.event_log_messages_.empty() && |
| 488 messages_in_frame > 0) { | 410 messages_in_frame > 0) { |
| 489 const RtcpReceiverEventLogMessage& event_message = | 411 const RtcpReceiverEventLogMessage& event_message = |
| 490 frame_log_messages.event_log_messages_.front(); | 412 frame_log_messages.event_log_messages_.front(); |
| 491 uint16 event_type_and_timestamp_delta = | 413 uint16 event_type_and_timestamp_delta = |
| 492 MergeEventTypeAndTimestampForWireFormat( | 414 MergeEventTypeAndTimestampForWireFormat( |
| 493 event_message.type, | 415 event_message.type, |
| 494 event_message.event_timestamp - event_timestamp_base); | 416 event_message.event_timestamp - event_timestamp_base); |
| 495 switch (event_message.type) { | 417 switch (event_message.type) { |
| 496 case FRAME_ACK_SENT: | 418 case FRAME_ACK_SENT: |
| 497 case FRAME_PLAYOUT: | 419 case FRAME_PLAYOUT: |
| 498 case FRAME_DECODED: | 420 case FRAME_DECODED: |
| 499 big_endian_writer.WriteU16( | 421 writer_.WriteU16( |
| 500 static_cast<uint16>(event_message.delay_delta.InMilliseconds())); | 422 static_cast<uint16>(event_message.delay_delta.InMilliseconds())); |
| 501 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | 423 writer_.WriteU16(event_type_and_timestamp_delta); |
| 502 break; | 424 break; |
| 503 case PACKET_RECEIVED: | 425 case PACKET_RECEIVED: |
| 504 big_endian_writer.WriteU16(event_message.packet_id); | 426 writer_.WriteU16(event_message.packet_id); |
| 505 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | 427 writer_.WriteU16(event_type_and_timestamp_delta); |
| 506 break; | 428 break; |
| 507 default: | 429 default: |
| 508 NOTREACHED(); | 430 NOTREACHED(); |
| 509 } | 431 } |
| 510 messages_in_frame--; | 432 messages_in_frame--; |
| 511 frame_log_messages.event_log_messages_.pop_front(); | 433 frame_log_messages.event_log_messages_.pop_front(); |
| 512 } | 434 } |
| 513 if (frame_log_messages.event_log_messages_.empty()) { | 435 if (frame_log_messages.event_log_messages_.empty()) { |
| 514 // We sent all messages on this frame; pop the frame header. | 436 // We sent all messages on this frame; pop the frame header. |
| 515 receiver_log_message.pop_front(); | 437 receiver_log_message.pop_front(); |
| 516 } | 438 } |
| 517 } | 439 } |
| 518 DCHECK_EQ(total_number_of_messages_to_send, 0u); | 440 DCHECK_EQ(total_number_of_messages_to_send, 0u); |
| 519 } | 441 } |
| 520 | 442 |
| 521 bool RtcpSender::BuildRtcpReceiverLogMessage( | 443 bool RtcpBuilder::BuildRtcpReceiverLogMessage( |
| 522 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, | 444 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, |
| 523 size_t start_size, | |
| 524 RtcpReceiverLogMessage* receiver_log_message, | 445 RtcpReceiverLogMessage* receiver_log_message, |
| 525 size_t* number_of_frames, | 446 size_t* total_number_of_messages_to_send) { |
| 526 size_t* total_number_of_messages_to_send, | 447 size_t number_of_frames = 0; |
| 527 size_t* rtcp_log_size) { | |
| 528 size_t remaining_space = | 448 size_t remaining_space = |
| 529 std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size); | 449 std::min<size_t>(kMaxReceiverLogBytes, writer_.remaining()); |
| 530 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + | 450 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + |
| 531 kRtcpReceiverEventLogSize) { | 451 kRtcpReceiverEventLogSize) { |
| 532 return false; | 452 return false; |
| 533 } | 453 } |
| 534 | 454 |
| 535 // We use this to do event timestamp sorting and truncating for events of | 455 // We use this to do event timestamp sorting and truncating for events of |
| 536 // a single frame. | 456 // a single frame. |
| 537 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; | 457 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; |
| 538 | 458 |
| 539 // Account for the RTCP header for an application-defined packet. | 459 // Account for the RTCP header for an application-defined packet. |
| 540 remaining_space -= kRtcpCastLogHeaderSize; | 460 remaining_space -= kRtcpCastLogHeaderSize; |
| 541 | 461 |
| 542 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = | 462 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = |
| 543 rtcp_events.rbegin(); | 463 rtcp_events.rbegin(); |
| 544 | 464 |
| 545 while (rit != rtcp_events.rend() && | 465 while (rit != rtcp_events.rend() && |
| 546 remaining_space >= | 466 remaining_space >= |
| 547 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { | 467 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { |
| 548 const RtpTimestamp rtp_timestamp = rit->first; | 468 const RtpTimestamp rtp_timestamp = rit->first; |
| 549 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); | 469 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); |
| 550 remaining_space -= kRtcpReceiverFrameLogSize; | 470 remaining_space -= kRtcpReceiverFrameLogSize; |
| 551 ++*number_of_frames; | 471 ++number_of_frames; |
| 552 | 472 |
| 553 // Get all events of a single frame. | 473 // Get all events of a single frame. |
| 554 sorted_log_messages.clear(); | 474 sorted_log_messages.clear(); |
| 555 do { | 475 do { |
| 556 RtcpReceiverEventLogMessage event_log_message; | 476 RtcpReceiverEventLogMessage event_log_message; |
| 557 event_log_message.type = rit->second.type; | 477 event_log_message.type = rit->second.type; |
| 558 event_log_message.event_timestamp = rit->second.timestamp; | 478 event_log_message.event_timestamp = rit->second.timestamp; |
| 559 event_log_message.delay_delta = rit->second.delay_delta; | 479 event_log_message.delay_delta = rit->second.delay_delta; |
| 560 event_log_message.packet_id = rit->second.packet_id; | 480 event_log_message.packet_id = rit->second.packet_id; |
| 561 sorted_log_messages.push_back(event_log_message); | 481 sorted_log_messages.push_back(event_log_message); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 | 514 |
| 595 // We don't try to match RTP timestamps of redundancy frame logs with those | 515 // We don't try to match RTP timestamps of redundancy frame logs with those |
| 596 // from the newest set (which would save the space of an extra RTP timestamp | 516 // from the newest set (which would save the space of an extra RTP timestamp |
| 597 // over the wire). Unless the redundancy frame logs are very recent, it's | 517 // over the wire). Unless the redundancy frame logs are very recent, it's |
| 598 // unlikely there will be a match anyway. | 518 // unlikely there will be a match anyway. |
| 599 if (rtcp_events_history_.size() > kFirstRedundancyOffset) { | 519 if (rtcp_events_history_.size() > kFirstRedundancyOffset) { |
| 600 // Add first redundnacy messages, if enough space remaining | 520 // Add first redundnacy messages, if enough space remaining |
| 601 AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset], | 521 AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset], |
| 602 receiver_log_message, | 522 receiver_log_message, |
| 603 &remaining_space, | 523 &remaining_space, |
| 604 number_of_frames, | 524 &number_of_frames, |
| 605 total_number_of_messages_to_send); | 525 total_number_of_messages_to_send); |
| 606 } | 526 } |
| 607 | 527 |
| 608 if (rtcp_events_history_.size() > kSecondRedundancyOffset) { | 528 if (rtcp_events_history_.size() > kSecondRedundancyOffset) { |
| 609 // Add second redundancy messages, if enough space remaining | 529 // Add second redundancy messages, if enough space remaining |
| 610 AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset], | 530 AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset], |
| 611 receiver_log_message, | 531 receiver_log_message, |
| 612 &remaining_space, | 532 &remaining_space, |
| 613 number_of_frames, | 533 &number_of_frames, |
| 614 total_number_of_messages_to_send); | 534 total_number_of_messages_to_send); |
| 615 } | 535 } |
| 616 | 536 |
| 617 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { | 537 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { |
| 618 rtcp_events_history_.pop_back(); | 538 rtcp_events_history_.pop_back(); |
| 619 } | 539 } |
| 620 | 540 |
| 621 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); | 541 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); |
| 622 | 542 |
| 623 *rtcp_log_size = | 543 VLOG(3) << "number of frames: " << number_of_frames; |
| 624 kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize + | |
| 625 *total_number_of_messages_to_send * kRtcpReceiverEventLogSize; | |
| 626 DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size) | |
| 627 << "Not enough buffer space."; | |
| 628 | |
| 629 VLOG(3) << "number of frames: " << *number_of_frames; | |
| 630 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; | 544 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; |
| 631 VLOG(3) << "rtcp log size: " << *rtcp_log_size; | 545 return number_of_frames > 0; |
| 632 return *number_of_frames > 0; | |
| 633 } | 546 } |
| 634 | 547 |
| 635 } // namespace cast | 548 } // namespace cast |
| 636 } // namespace media | 549 } // namespace media |
| OLD | NEW |