Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/rtcp/rtcp_sender.h" | 5 #include "media/cast/rtcp/rtcp_sender.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "media/cast/pacing/paced_sender.h" | 12 #include "media/cast/pacing/paced_sender.h" |
| 13 #include "media/cast/rtcp/rtcp_utility.h" | 13 #include "media/cast/rtcp/rtcp_utility.h" |
| 14 #include "net/base/big_endian.h" | 14 #include "net/base/big_endian.h" |
| 15 | 15 |
| 16 namespace { | |
| 17 | |
| 18 uint16 MergeEventTypeAndTimestampForWireFormat( | |
| 19 const media::cast::CastLoggingEvent& event, | |
| 20 const base::TimeDelta& time_delta) { | |
| 21 int64 time_delta_ms = time_delta.InMilliseconds(); | |
| 22 // Max delta is 4096 milliseconds. | |
| 23 DCHECK_GE(GG_INT64_C(0xfff), time_delta_ms); | |
| 24 | |
| 25 uint16 event_type_and_timestamp_delta = | |
| 26 static_cast<uint16>(time_delta_ms & 0xfff); | |
| 27 | |
| 28 uint16 event_type = 0; | |
| 29 switch (event) { | |
| 30 case media::cast::kAckSent: | |
| 31 event_type = 1; | |
| 32 break; | |
| 33 case media::cast::kAudioPlayoutDelay: | |
| 34 event_type = 2; | |
| 35 break; | |
| 36 case media::cast::kAudioFrameDecoded: | |
| 37 event_type = 3; | |
| 38 break; | |
| 39 case media::cast::kVideoFrameDecoded: | |
| 40 event_type = 4; | |
| 41 break; | |
| 42 case media::cast::kVideoRenderDelay: | |
| 43 event_type = 5; | |
| 44 break; | |
| 45 case media::cast::kPacketReceived: | |
| 46 event_type = 6; | |
| 47 break; | |
| 48 default: | |
| 49 NOTREACHED(); | |
|
mikhal
2013/11/21 16:43:20
The receiver also includes jitter and packet loss
pwestin
2013/11/22 18:50:47
The difference is that this is intended for timing
| |
| 50 } | |
| 51 DCHECK(!(event_type & 0xfff0)); | |
| 52 return (event_type << 12) + event_type_and_timestamp_delta; | |
| 53 } | |
| 54 | |
| 55 bool ScanRtcpReceiverLogMessage( | |
| 56 const media::cast::RtcpReceiverLogMessage& receiver_log_message, | |
| 57 size_t start_size, | |
| 58 size_t* number_of_frames, | |
| 59 size_t* total_number_of_messages_to_send, | |
| 60 size_t* rtcp_log_size) { | |
| 61 if (receiver_log_message.empty()) return false; | |
| 62 | |
| 63 size_t remaining_space = media::cast::kIpPacketSize - start_size; | |
| 64 | |
| 65 // We must have space for at least one message | |
| 66 DCHECK_GE(remaining_space, 16) << "Not enough buffer space"; | |
| 67 if (remaining_space < 16) return false; | |
| 68 | |
| 69 // Account for the RTCP header for an application-defined packet. | |
| 70 remaining_space -= 12; | |
|
mikhal
2013/11/21 16:43:20
use consts, here and elsewhere.
pwestin
2013/11/22 18:50:47
Done.
| |
| 71 | |
| 72 media::cast::RtcpReceiverLogMessage::const_iterator frame_it = | |
| 73 receiver_log_message.begin(); | |
| 74 for (; frame_it != receiver_log_message.end(); ++frame_it) { | |
| 75 (*number_of_frames)++; | |
| 76 remaining_space -= 8; | |
| 77 | |
| 78 size_t messages_in_frame = frame_it->event_log_messages.size(); | |
| 79 size_t remaining_space_in_messages = remaining_space / 4; | |
| 80 size_t messages_to_send = std::min(messages_in_frame, | |
| 81 remaining_space_in_messages); | |
| 82 if (messages_to_send > media::cast::kRtcpMaxReceiverLogMessages) { | |
| 83 // We can't send more than 256 messages. | |
| 84 remaining_space -= media::cast::kRtcpMaxReceiverLogMessages * 4; | |
| 85 *total_number_of_messages_to_send += | |
| 86 media::cast::kRtcpMaxReceiverLogMessages; | |
| 87 break; | |
| 88 } | |
| 89 remaining_space -= messages_to_send * 4; | |
| 90 *total_number_of_messages_to_send += messages_to_send; | |
| 91 | |
| 92 if (remaining_space < 12) { | |
| 93 // Make sure that we have room for at least one more message. | |
| 94 break; | |
| 95 } | |
| 96 } | |
| 97 *rtcp_log_size = 12 + *number_of_frames * 8 + | |
| 98 *total_number_of_messages_to_send * 4; | |
| 99 DCHECK_GE(media::cast::kIpPacketSize, | |
| 100 start_size + *rtcp_log_size) << "Not enough buffer space"; | |
| 101 | |
| 102 VLOG(1) << "number of frames " << *number_of_frames; | |
| 103 VLOG(1) << "total messages to send " << *total_number_of_messages_to_send; | |
| 104 VLOG(1) << "rtcp log size " << *rtcp_log_size; | |
| 105 return true; | |
| 106 } | |
| 107 } // namespace | |
| 108 | |
| 16 namespace media { | 109 namespace media { |
| 17 namespace cast { | 110 namespace cast { |
| 18 | 111 |
| 19 static const size_t kRtcpMaxNackFields = 253; | |
| 20 static const size_t kRtcpMaxCastLossFields = 100; | |
| 21 | |
| 22 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, | 112 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, |
| 23 uint32 sending_ssrc, | 113 uint32 sending_ssrc, |
| 24 const std::string& c_name) | 114 const std::string& c_name) |
| 25 : ssrc_(sending_ssrc), | 115 : ssrc_(sending_ssrc), |
| 26 c_name_(c_name), | 116 c_name_(c_name), |
| 27 transport_(outgoing_transport) { | 117 transport_(outgoing_transport) { |
| 28 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; | 118 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; |
| 29 } | 119 } |
| 30 | 120 |
| 31 RtcpSender::~RtcpSender() {} | 121 RtcpSender::~RtcpSender() {} |
| 32 | 122 |
| 33 void RtcpSender::SendRtcpFromRtpSender(uint32 packet_type_flags, | 123 void RtcpSender::SendRtcpFromRtpSender(uint32 packet_type_flags, |
| 34 const RtcpSenderInfo* sender_info, | 124 const RtcpSenderInfo* sender_info, |
| 35 const RtcpDlrrReportBlock* dlrr, | 125 const RtcpDlrrReportBlock* dlrr, |
| 36 const RtcpSenderLogMessage* sender_log) { | 126 RtcpSenderLogMessage* sender_log) { |
| 37 if (packet_type_flags & kRtcpRr || | 127 if (packet_type_flags & kRtcpRr || |
| 38 packet_type_flags & kRtcpPli || | 128 packet_type_flags & kRtcpPli || |
| 39 packet_type_flags & kRtcpRrtr || | 129 packet_type_flags & kRtcpRrtr || |
| 40 packet_type_flags & kRtcpCast || | 130 packet_type_flags & kRtcpCast || |
| 41 packet_type_flags & kRtcpReceiverLog || | 131 packet_type_flags & kRtcpReceiverLog || |
| 42 packet_type_flags & kRtcpRpsi || | 132 packet_type_flags & kRtcpRpsi || |
| 43 packet_type_flags & kRtcpRemb || | 133 packet_type_flags & kRtcpRemb || |
| 44 packet_type_flags & kRtcpNack) { | 134 packet_type_flags & kRtcpNack) { |
| 45 NOTREACHED() << "Invalid argument"; | 135 NOTREACHED() << "Invalid argument"; |
| 46 } | 136 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 67 return; // Sanity don't send empty packets. | 157 return; // Sanity don't send empty packets. |
| 68 | 158 |
| 69 transport_->SendRtcpPacket(packet); | 159 transport_->SendRtcpPacket(packet); |
| 70 } | 160 } |
| 71 | 161 |
| 72 void RtcpSender::SendRtcpFromRtpReceiver( | 162 void RtcpSender::SendRtcpFromRtpReceiver( |
| 73 uint32 packet_type_flags, | 163 uint32 packet_type_flags, |
| 74 const RtcpReportBlock* report_block, | 164 const RtcpReportBlock* report_block, |
| 75 const RtcpReceiverReferenceTimeReport* rrtr, | 165 const RtcpReceiverReferenceTimeReport* rrtr, |
| 76 const RtcpCastMessage* cast_message, | 166 const RtcpCastMessage* cast_message, |
| 77 const RtcpReceiverLogMessage* receiver_log) { | 167 RtcpReceiverLogMessage* receiver_log) { |
| 78 if (packet_type_flags & kRtcpSr || | 168 if (packet_type_flags & kRtcpSr || |
| 79 packet_type_flags & kRtcpDlrr || | 169 packet_type_flags & kRtcpDlrr || |
| 80 packet_type_flags & kRtcpSenderLog) { | 170 packet_type_flags & kRtcpSenderLog) { |
| 81 NOTREACHED() << "Invalid argument"; | 171 NOTREACHED() << "Invalid argument"; |
| 82 } | 172 } |
| 83 if (packet_type_flags & kRtcpPli || | 173 if (packet_type_flags & kRtcpPli || |
| 84 packet_type_flags & kRtcpRpsi || | 174 packet_type_flags & kRtcpRpsi || |
| 85 packet_type_flags & kRtcpRemb || | 175 packet_type_flags & kRtcpRemb || |
| 86 packet_type_flags & kRtcpNack) { | 176 packet_type_flags & kRtcpNack) { |
| 87 // Implement these for webrtc interop. | 177 // Implement these for webrtc interop. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 // Sender report. | 212 // Sender report. |
| 123 size_t start_size = packet->size(); | 213 size_t start_size = packet->size(); |
| 124 DCHECK_LT(start_size + 52, kIpPacketSize) << "Not enough buffer space"; | 214 DCHECK_LT(start_size + 52, kIpPacketSize) << "Not enough buffer space"; |
| 125 if (start_size + 52 > kIpPacketSize) return; | 215 if (start_size + 52 > kIpPacketSize) return; |
| 126 | 216 |
| 127 uint16 number_of_rows = (report_block) ? 12 : 6; | 217 uint16 number_of_rows = (report_block) ? 12 : 6; |
| 128 packet->resize(start_size + 28); | 218 packet->resize(start_size + 28); |
| 129 | 219 |
| 130 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 28); | 220 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 28); |
| 131 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); | 221 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); |
| 132 big_endian_writer.WriteU8(200); | 222 big_endian_writer.WriteU8(kPacketTypeSenderReport); |
| 133 big_endian_writer.WriteU16(number_of_rows); | 223 big_endian_writer.WriteU16(number_of_rows); |
| 134 big_endian_writer.WriteU32(ssrc_); | 224 big_endian_writer.WriteU32(ssrc_); |
| 135 big_endian_writer.WriteU32(sender_info.ntp_seconds); | 225 big_endian_writer.WriteU32(sender_info.ntp_seconds); |
| 136 big_endian_writer.WriteU32(sender_info.ntp_fraction); | 226 big_endian_writer.WriteU32(sender_info.ntp_fraction); |
| 137 big_endian_writer.WriteU32(sender_info.rtp_timestamp); | 227 big_endian_writer.WriteU32(sender_info.rtp_timestamp); |
| 138 big_endian_writer.WriteU32(sender_info.send_packet_count); | 228 big_endian_writer.WriteU32(sender_info.send_packet_count); |
| 139 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); | 229 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); |
| 140 | 230 |
| 141 if (report_block) { | 231 if (report_block) { |
| 142 AddReportBlocks(*report_block, packet); // Adds 24 bytes. | 232 AddReportBlocks(*report_block, packet); // Adds 24 bytes. |
| 143 } | 233 } |
| 144 } | 234 } |
| 145 | 235 |
| 146 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, | 236 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, |
| 147 std::vector<uint8>* packet) const { | 237 std::vector<uint8>* packet) const { |
| 148 size_t start_size = packet->size(); | 238 size_t start_size = packet->size(); |
| 149 DCHECK_LT(start_size + 32, kIpPacketSize) << "Not enough buffer space"; | 239 DCHECK_LT(start_size + 32, kIpPacketSize) << "Not enough buffer space"; |
| 150 if (start_size + 32 > kIpPacketSize) return; | 240 if (start_size + 32 > kIpPacketSize) return; |
| 151 | 241 |
| 152 uint16 number_of_rows = (report_block) ? 7 : 1; | 242 uint16 number_of_rows = (report_block) ? 7 : 1; |
| 153 packet->resize(start_size + 8); | 243 packet->resize(start_size + 8); |
| 154 | 244 |
| 155 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8); | 245 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8); |
| 156 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); | 246 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); |
| 157 big_endian_writer.WriteU8(201); | 247 big_endian_writer.WriteU8(kPacketTypeReceiverReport); |
| 158 big_endian_writer.WriteU16(number_of_rows); | 248 big_endian_writer.WriteU16(number_of_rows); |
| 159 big_endian_writer.WriteU32(ssrc_); | 249 big_endian_writer.WriteU32(ssrc_); |
| 160 | 250 |
| 161 if (report_block) { | 251 if (report_block) { |
| 162 AddReportBlocks(*report_block, packet); // Adds 24 bytes. | 252 AddReportBlocks(*report_block, packet); // Adds 24 bytes. |
| 163 } | 253 } |
| 164 } | 254 } |
| 165 | 255 |
| 166 void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block, | 256 void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block, |
| 167 std::vector<uint8>* packet) const { | 257 std::vector<uint8>* packet) const { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 196 DCHECK_LT(start_size + 12 + c_name_.length(), kIpPacketSize) | 286 DCHECK_LT(start_size + 12 + c_name_.length(), kIpPacketSize) |
| 197 << "Not enough buffer space"; | 287 << "Not enough buffer space"; |
| 198 if (start_size + 12 > kIpPacketSize) return; | 288 if (start_size + 12 > kIpPacketSize) return; |
| 199 | 289 |
| 200 // SDES Source Description. | 290 // SDES Source Description. |
| 201 packet->resize(start_size + 10); | 291 packet->resize(start_size + 10); |
| 202 | 292 |
| 203 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10); | 293 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10); |
| 204 // We always need to add one SDES CNAME. | 294 // We always need to add one SDES CNAME. |
| 205 big_endian_writer.WriteU8(0x80 + 1); | 295 big_endian_writer.WriteU8(0x80 + 1); |
| 206 big_endian_writer.WriteU8(202); | 296 big_endian_writer.WriteU8(kPacketTypeSdes); |
| 207 | 297 |
| 208 // Handle SDES length later on. | 298 // Handle SDES length later on. |
| 209 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3; | 299 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3; |
| 210 big_endian_writer.WriteU16(0); | 300 big_endian_writer.WriteU16(0); |
| 211 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 301 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 212 big_endian_writer.WriteU8(1); // CNAME = 1 | 302 big_endian_writer.WriteU8(1); // CNAME = 1 |
| 213 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length())); | 303 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length())); |
| 214 | 304 |
| 215 size_t sdes_length = 10 + c_name_.length(); | 305 size_t sdes_length = 10 + c_name_.length(); |
| 216 packet->insert(packet->end(), c_name_.c_str(), | 306 packet->insert(packet->end(), c_name_.c_str(), |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 238 std::vector<uint8>* packet) const { | 328 std::vector<uint8>* packet) const { |
| 239 size_t start_size = packet->size(); | 329 size_t start_size = packet->size(); |
| 240 DCHECK_LT(start_size + 12, kIpPacketSize) << "Not enough buffer space"; | 330 DCHECK_LT(start_size + 12, kIpPacketSize) << "Not enough buffer space"; |
| 241 if (start_size + 12 > kIpPacketSize) return; | 331 if (start_size + 12 > kIpPacketSize) return; |
| 242 | 332 |
| 243 packet->resize(start_size + 12); | 333 packet->resize(start_size + 12); |
| 244 | 334 |
| 245 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 12); | 335 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 12); |
| 246 uint8 FMT = 1; // Picture loss indicator. | 336 uint8 FMT = 1; // Picture loss indicator. |
| 247 big_endian_writer.WriteU8(0x80 + FMT); | 337 big_endian_writer.WriteU8(0x80 + FMT); |
| 248 big_endian_writer.WriteU8(206); | 338 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); |
| 249 big_endian_writer.WriteU16(2); // Used fixed length of 2. | 339 big_endian_writer.WriteU16(2); // Used fixed length of 2. |
| 250 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 340 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 251 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC. | 341 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC. |
| 252 TRACE_EVENT_INSTANT2("cast_rtcp", "RtcpSender::PLI", TRACE_EVENT_SCOPE_THREAD, | 342 TRACE_EVENT_INSTANT2("cast_rtcp", "RtcpSender::PLI", TRACE_EVENT_SCOPE_THREAD, |
| 253 "remote_ssrc", remote_ssrc, | 343 "remote_ssrc", remote_ssrc, |
| 254 "ssrc", ssrc_); | 344 "ssrc", ssrc_); |
| 255 } | 345 } |
| 256 | 346 |
| 257 /* | 347 /* |
| 258 0 1 2 3 | 348 0 1 2 3 |
| 259 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 | 349 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 |
| 260 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 350 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 261 | PB |0| Payload Type| Native Rpsi bit string | | 351 | PB |0| Payload Type| Native Rpsi bit string | |
| 262 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 352 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 263 | defined per codec ... | Padding (0) | | 353 | defined per codec ... | Padding (0) | |
| 264 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 354 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 265 */ | 355 */ |
| 266 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, | 356 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, |
| 267 std::vector<uint8>* packet) const { | 357 std::vector<uint8>* packet) const { |
| 268 size_t start_size = packet->size(); | 358 size_t start_size = packet->size(); |
| 269 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space"; | 359 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space"; |
| 270 if (start_size + 24 > kIpPacketSize) return; | 360 if (start_size + 24 > kIpPacketSize) return; |
| 271 | 361 |
| 272 packet->resize(start_size + 24); | 362 packet->resize(start_size + 24); |
| 273 | 363 |
| 274 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24); | 364 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24); |
| 275 uint8 FMT = 3; // Reference Picture Selection Indication. | 365 uint8 FMT = 3; // Reference Picture Selection Indication. |
| 276 big_endian_writer.WriteU8(0x80 + FMT); | 366 big_endian_writer.WriteU8(0x80 + FMT); |
| 277 big_endian_writer.WriteU8(206); | 367 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); |
| 278 | 368 |
| 279 // Calculate length. | 369 // Calculate length. |
| 280 uint32 bits_required = 7; | 370 uint32 bits_required = 7; |
| 281 uint8 bytes_required = 1; | 371 uint8 bytes_required = 1; |
| 282 while ((rpsi->picture_id >> bits_required) > 0) { | 372 while ((rpsi->picture_id >> bits_required) > 0) { |
| 283 bits_required += 7; | 373 bits_required += 7; |
| 284 bytes_required++; | 374 bytes_required++; |
| 285 } | 375 } |
| 286 uint8 size = 3; | 376 uint8 size = 3; |
| 287 if (bytes_required > 6) { | 377 if (bytes_required > 6) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 << "Not enough buffer space"; | 414 << "Not enough buffer space"; |
| 325 if (start_size + remb_size > kIpPacketSize) return; | 415 if (start_size + remb_size > kIpPacketSize) return; |
| 326 | 416 |
| 327 packet->resize(start_size + remb_size); | 417 packet->resize(start_size + remb_size); |
| 328 | 418 |
| 329 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size); | 419 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size); |
| 330 | 420 |
| 331 // Add application layer feedback. | 421 // Add application layer feedback. |
| 332 uint8 FMT = 15; | 422 uint8 FMT = 15; |
| 333 big_endian_writer.WriteU8(0x80 + FMT); | 423 big_endian_writer.WriteU8(0x80 + FMT); |
| 334 big_endian_writer.WriteU8(206); | 424 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); |
| 335 big_endian_writer.WriteU8(0); | 425 big_endian_writer.WriteU8(0); |
| 336 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4)); | 426 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4)); |
| 337 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 427 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 338 big_endian_writer.WriteU32(0); // Remote SSRC must be 0. | 428 big_endian_writer.WriteU32(0); // Remote SSRC must be 0. |
| 339 big_endian_writer.WriteU32(kRemb); | 429 big_endian_writer.WriteU32(kRemb); |
| 340 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size())); | 430 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size())); |
| 341 | 431 |
| 342 // 6 bit exponent and a 18 bit mantissa. | 432 // 6 bit exponent and a 18 bit mantissa. |
| 343 uint8 bitrate_exponent; | 433 uint8 bitrate_exponent; |
| 344 uint32 bitrate_mantissa; | 434 uint32 bitrate_mantissa; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 364 size_t start_size = packet->size(); | 454 size_t start_size = packet->size(); |
| 365 DCHECK_LT(start_size + 16, kIpPacketSize) << "Not enough buffer space"; | 455 DCHECK_LT(start_size + 16, kIpPacketSize) << "Not enough buffer space"; |
| 366 if (start_size + 16 > kIpPacketSize) return; | 456 if (start_size + 16 > kIpPacketSize) return; |
| 367 | 457 |
| 368 packet->resize(start_size + 16); | 458 packet->resize(start_size + 16); |
| 369 | 459 |
| 370 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16); | 460 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16); |
| 371 | 461 |
| 372 uint8 FMT = 1; | 462 uint8 FMT = 1; |
| 373 big_endian_writer.WriteU8(0x80 + FMT); | 463 big_endian_writer.WriteU8(0x80 + FMT); |
| 374 big_endian_writer.WriteU8(205); | 464 big_endian_writer.WriteU8(kPacketTypeGenericRtpFeedback); |
| 375 big_endian_writer.WriteU8(0); | 465 big_endian_writer.WriteU8(0); |
| 376 size_t nack_size_pos = start_size + 3; | 466 size_t nack_size_pos = start_size + 3; |
| 377 big_endian_writer.WriteU8(3); | 467 big_endian_writer.WriteU8(3); |
| 378 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 468 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 379 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC. | 469 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC. |
| 380 | 470 |
| 381 // Build NACK bitmasks and write them to the Rtcp message. | 471 // Build NACK bitmasks and write them to the Rtcp message. |
| 382 // The nack list should be sorted and not contain duplicates. | 472 // The nack list should be sorted and not contain duplicates. |
| 383 size_t number_of_nack_fields = 0; | 473 size_t number_of_nack_fields = 0; |
| 384 size_t max_number_of_nack_fields = std::min<size_t>(kRtcpMaxNackFields, | 474 size_t max_number_of_nack_fields = std::min<size_t>(kRtcpMaxNackFields, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 | 508 |
| 419 void RtcpSender::BuildBye(std::vector<uint8>* packet) const { | 509 void RtcpSender::BuildBye(std::vector<uint8>* packet) const { |
| 420 size_t start_size = packet->size(); | 510 size_t start_size = packet->size(); |
| 421 DCHECK_LT(start_size + 8, kIpPacketSize) << "Not enough buffer space"; | 511 DCHECK_LT(start_size + 8, kIpPacketSize) << "Not enough buffer space"; |
| 422 if (start_size + 8 > kIpPacketSize) return; | 512 if (start_size + 8 > kIpPacketSize) return; |
| 423 | 513 |
| 424 packet->resize(start_size + 8); | 514 packet->resize(start_size + 8); |
| 425 | 515 |
| 426 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8); | 516 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8); |
| 427 big_endian_writer.WriteU8(0x80 + 1); | 517 big_endian_writer.WriteU8(0x80 + 1); |
| 428 big_endian_writer.WriteU8(203); | 518 big_endian_writer.WriteU8(kPacketTypeBye); |
| 429 big_endian_writer.WriteU16(1); // Length. | 519 big_endian_writer.WriteU16(1); // Length. |
| 430 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 520 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 431 } | 521 } |
| 432 | 522 |
| 433 /* | 523 /* |
| 434 0 1 2 3 | 524 0 1 2 3 |
| 435 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 | 525 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 |
| 436 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 526 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 437 |V=2|P|reserved | PT=XR=207 | length | | 527 |V=2|P|reserved | PT=XR=207 | length | |
| 438 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 528 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 450 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock* dlrr, | 540 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock* dlrr, |
| 451 std::vector<uint8>* packet) const { | 541 std::vector<uint8>* packet) const { |
| 452 size_t start_size = packet->size(); | 542 size_t start_size = packet->size(); |
| 453 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space"; | 543 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space"; |
| 454 if (start_size + 24 > kIpPacketSize) return; | 544 if (start_size + 24 > kIpPacketSize) return; |
| 455 | 545 |
| 456 packet->resize(start_size + 24); | 546 packet->resize(start_size + 24); |
| 457 | 547 |
| 458 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24); | 548 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24); |
| 459 big_endian_writer.WriteU8(0x80); | 549 big_endian_writer.WriteU8(0x80); |
| 460 big_endian_writer.WriteU8(207); | 550 big_endian_writer.WriteU8(kPacketTypeXr); |
| 461 big_endian_writer.WriteU16(5); // Length. | 551 big_endian_writer.WriteU16(5); // Length. |
| 462 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 552 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 463 big_endian_writer.WriteU8(5); // Add block type. | 553 big_endian_writer.WriteU8(5); // Add block type. |
| 464 big_endian_writer.WriteU8(0); // Add reserved. | 554 big_endian_writer.WriteU8(0); // Add reserved. |
| 465 big_endian_writer.WriteU16(3); // Block length. | 555 big_endian_writer.WriteU16(3); // Block length. |
| 466 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. | 556 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. |
| 467 big_endian_writer.WriteU32(dlrr->last_rr); | 557 big_endian_writer.WriteU32(dlrr->last_rr); |
| 468 big_endian_writer.WriteU32(dlrr->delay_since_last_rr); | 558 big_endian_writer.WriteU32(dlrr->delay_since_last_rr); |
| 469 } | 559 } |
| 470 | 560 |
| 471 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, | 561 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, |
| 472 std::vector<uint8>* packet) const { | 562 std::vector<uint8>* packet) const { |
| 473 size_t start_size = packet->size(); | 563 size_t start_size = packet->size(); |
| 474 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space"; | 564 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space"; |
| 475 if (start_size + 20 > kIpPacketSize) return; | 565 if (start_size + 20 > kIpPacketSize) return; |
| 476 | 566 |
| 477 packet->resize(start_size + 20); | 567 packet->resize(start_size + 20); |
| 478 | 568 |
| 479 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20); | 569 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20); |
| 480 | 570 |
| 481 big_endian_writer.WriteU8(0x80); | 571 big_endian_writer.WriteU8(0x80); |
| 482 big_endian_writer.WriteU8(207); | 572 big_endian_writer.WriteU8(kPacketTypeXr); |
| 483 big_endian_writer.WriteU16(4); // Length. | 573 big_endian_writer.WriteU16(4); // Length. |
| 484 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 574 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 485 big_endian_writer.WriteU8(4); // Add block type. | 575 big_endian_writer.WriteU8(4); // Add block type. |
| 486 big_endian_writer.WriteU8(0); // Add reserved. | 576 big_endian_writer.WriteU8(0); // Add reserved. |
| 487 big_endian_writer.WriteU16(2); // Block length. | 577 big_endian_writer.WriteU16(2); // Block length. |
| 488 | 578 |
| 489 // Add the media (received RTP) SSRC. | 579 // Add the media (received RTP) SSRC. |
| 490 big_endian_writer.WriteU32(rrtr->ntp_seconds); | 580 big_endian_writer.WriteU32(rrtr->ntp_seconds); |
| 491 big_endian_writer.WriteU32(rrtr->ntp_fraction); | 581 big_endian_writer.WriteU32(rrtr->ntp_fraction); |
| 492 } | 582 } |
| 493 | 583 |
| 494 void RtcpSender::BuildCast(const RtcpCastMessage* cast, | 584 void RtcpSender::BuildCast(const RtcpCastMessage* cast, |
| 495 std::vector<uint8>* packet) const { | 585 std::vector<uint8>* packet) const { |
| 496 size_t start_size = packet->size(); | 586 size_t start_size = packet->size(); |
| 497 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space"; | 587 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space"; |
| 498 if (start_size + 20 > kIpPacketSize) return; | 588 if (start_size + 20 > kIpPacketSize) return; |
| 499 | 589 |
| 500 packet->resize(start_size + 20); | 590 packet->resize(start_size + 20); |
| 501 | 591 |
| 502 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20); | 592 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20); |
| 503 uint8 FMT = 15; // Application layer feedback. | 593 uint8 FMT = 15; // Application layer feedback. |
| 504 big_endian_writer.WriteU8(0x80 + FMT); | 594 big_endian_writer.WriteU8(0x80 + FMT); |
| 505 big_endian_writer.WriteU8(206); | 595 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); |
| 506 big_endian_writer.WriteU8(0); | 596 big_endian_writer.WriteU8(0); |
| 507 size_t cast_size_pos = start_size + 3; // Save length position. | 597 size_t cast_size_pos = start_size + 3; // Save length position. |
| 508 big_endian_writer.WriteU8(4); | 598 big_endian_writer.WriteU8(4); |
| 509 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 599 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 510 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC. | 600 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC. |
| 511 big_endian_writer.WriteU32(kCast); | 601 big_endian_writer.WriteU32(kCast); |
| 512 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_)); | 602 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_)); |
| 513 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. | 603 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. |
| 514 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. | 604 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. |
| 515 big_endian_writer.WriteU8(0); // Reserved. | 605 big_endian_writer.WriteU8(0); // Reserved. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 } | 656 } |
| 567 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); | 657 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); |
| 568 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); | 658 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); |
| 569 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); | 659 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); |
| 570 | 660 |
| 571 // Frames with missing packets. | 661 // Frames with missing packets. |
| 572 TRACE_COUNTER_ID1("cast_rtcp", "RtcpSender::CastNACK", ssrc_, | 662 TRACE_COUNTER_ID1("cast_rtcp", "RtcpSender::CastNACK", ssrc_, |
| 573 cast->missing_frames_and_packets_.size()); | 663 cast->missing_frames_and_packets_.size()); |
| 574 } | 664 } |
| 575 | 665 |
| 576 void RtcpSender::BuildSenderLog(const RtcpSenderLogMessage* sender_log_message, | 666 void RtcpSender::BuildSenderLog(RtcpSenderLogMessage* sender_log_message, |
| 577 std::vector<uint8>* packet) const { | 667 std::vector<uint8>* packet) const { |
| 578 // TODO(pwestin): Implement. | 668 DCHECK(sender_log_message); |
| 579 NOTIMPLEMENTED(); | 669 DCHECK(packet); |
| 670 static const size_t kRtcpMinSendLogSize = 16; | |
| 671 size_t start_size = packet->size(); | |
| 672 size_t remaining_space = kIpPacketSize - start_size; | |
| 673 DCHECK_GE(remaining_space, kRtcpMinSendLogSize) << "Not enough buffer space"; | |
| 674 if (remaining_space < kRtcpMinSendLogSize) return; | |
| 675 | |
| 676 size_t space_for_x_messages = (remaining_space - 12) / 4; | |
| 677 size_t number_of_messages = std::min(space_for_x_messages, | |
| 678 sender_log_message->size()); | |
| 679 | |
| 680 size_t log_size = 12 + number_of_messages * 4; | |
| 681 packet->resize(start_size + log_size); | |
| 682 | |
| 683 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), log_size); | |
| 684 big_endian_writer.WriteU8(0x80 + kSenderLogSubtype); | |
| 685 big_endian_writer.WriteU8(kPacketTypeApplicationDefined); | |
| 686 big_endian_writer.WriteU16(2 + number_of_messages); | |
| 687 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 688 big_endian_writer.WriteU32(kCast); | |
| 689 | |
| 690 for (; number_of_messages > 0; --number_of_messages) { | |
| 691 DCHECK(!sender_log_message->empty()); | |
| 692 const RtcpSenderFrameLogMessage& message = sender_log_message->front(); | |
| 693 big_endian_writer.WriteU8(static_cast<uint8>(message.frame_status)); | |
| 694 // We send the 24 east significant bits of the RTP timestamp. | |
| 695 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 16)); | |
| 696 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 8)); | |
| 697 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp)); | |
| 698 sender_log_message->pop_front(); | |
| 699 } | |
| 580 } | 700 } |
| 581 | 701 |
| 582 void RtcpSender::BuildReceiverLog( | 702 void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message, |
| 583 const RtcpReceiverLogMessage* receiver_log_message, | 703 std::vector<uint8>* packet) const { |
| 584 std::vector<uint8>* packet) const { | 704 DCHECK(receiver_log_message); |
| 585 // TODO(pwestin): Implement. | 705 const size_t packet_start_size = packet->size(); |
| 586 NOTIMPLEMENTED(); | 706 size_t number_of_frames = 0; |
| 707 size_t total_number_of_messages_to_send = 0; | |
| 708 size_t rtcp_log_size = 0; | |
| 709 | |
| 710 if (!ScanRtcpReceiverLogMessage(*receiver_log_message, | |
| 711 packet_start_size, | |
| 712 &number_of_frames, | |
| 713 &total_number_of_messages_to_send, | |
| 714 &rtcp_log_size)) { | |
| 715 return; | |
| 716 } | |
| 717 packet->resize(packet_start_size + rtcp_log_size); | |
| 718 | |
| 719 net::BigEndianWriter big_endian_writer(&((*packet)[packet_start_size]), | |
| 720 rtcp_log_size); | |
| 721 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype); | |
| 722 big_endian_writer.WriteU8(kPacketTypeApplicationDefined); | |
| 723 big_endian_writer.WriteU16(2 + 2 * number_of_frames + | |
| 724 total_number_of_messages_to_send); | |
| 725 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
| 726 big_endian_writer.WriteU32(kCast); | |
| 727 | |
| 728 while (!receiver_log_message->empty() && | |
| 729 total_number_of_messages_to_send > 0) { | |
| 730 RtcpReceiverFrameLogMessage& frame_log_messages = | |
| 731 receiver_log_message->front(); | |
| 732 // Add our frame header. | |
| 733 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp); | |
| 734 size_t messages_in_frame = frame_log_messages.event_log_messages.size(); | |
| 735 if (messages_in_frame > total_number_of_messages_to_send) { | |
| 736 // We are running out of space. | |
| 737 messages_in_frame = total_number_of_messages_to_send; | |
| 738 } | |
| 739 // Keep track of how many messages we have left to send. | |
| 740 total_number_of_messages_to_send -= messages_in_frame; | |
| 741 | |
| 742 // On the wire format is number of messages - 1. | |
| 743 big_endian_writer.WriteU8(messages_in_frame - 1); | |
| 744 | |
| 745 base::TimeTicks event_timestamp_base = | |
| 746 frame_log_messages.event_log_messages.front().event_timestamp; | |
| 747 uint32 base_timestamp_ms = | |
| 748 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); | |
| 749 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); | |
| 750 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); | |
| 751 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms)); | |
| 752 | |
| 753 while (!frame_log_messages.event_log_messages.empty() && | |
| 754 messages_in_frame > 0) { | |
| 755 const RtcpReceiverEventLogMessage& event_message = | |
| 756 frame_log_messages.event_log_messages.front(); | |
| 757 uint16 event_type_and_timestamp_delta = | |
| 758 MergeEventTypeAndTimestampForWireFormat(event_message.type, | |
| 759 event_message.event_timestamp - event_timestamp_base); | |
| 760 switch (event_message.type) { | |
| 761 case kAckSent: | |
| 762 case kAudioPlayoutDelay: | |
| 763 case kAudioFrameDecoded: | |
| 764 case kVideoFrameDecoded: | |
| 765 case kVideoRenderDelay: | |
| 766 big_endian_writer.WriteU16(static_cast<uint16>( | |
| 767 event_message.delay_delta.InMilliseconds())); | |
| 768 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | |
| 769 break; | |
| 770 case kPacketReceived: | |
| 771 big_endian_writer.WriteU16(event_message.packet_id); | |
| 772 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | |
| 773 break; | |
| 774 default: | |
| 775 NOTREACHED(); | |
| 776 } | |
| 777 messages_in_frame--; | |
| 778 frame_log_messages.event_log_messages.pop_front(); | |
| 779 } | |
| 780 if (frame_log_messages.event_log_messages.empty()) { | |
| 781 // We sent all messages on this frame; pop the frame header. | |
| 782 receiver_log_message->pop_front(); | |
| 783 } | |
| 784 } | |
| 785 DCHECK_EQ(total_number_of_messages_to_send, 0); | |
| 587 } | 786 } |
| 588 | 787 |
| 589 } // namespace cast | 788 } // namespace cast |
| 590 } // namespace media | 789 } // namespace media |
| OLD | NEW |