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_sender.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" | 12 #include "base/big_endian.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "media/cast/cast_environment.h" | |
15 #include "media/cast/net/cast_transport_defines.h" | 14 #include "media/cast/net/cast_transport_defines.h" |
16 #include "media/cast/net/pacing/paced_sender.h" | 15 #include "media/cast/net/pacing/paced_sender.h" |
17 #include "media/cast/net/rtcp/rtcp_defines.h" | 16 #include "media/cast/net/rtcp/rtcp_defines.h" |
18 #include "media/cast/net/rtcp/rtcp_utility.h" | 17 #include "media/cast/net/rtcp/rtcp_utility.h" |
19 | 18 |
20 namespace media { | 19 namespace media { |
21 namespace cast { | 20 namespace cast { |
22 namespace { | 21 namespace { |
23 | 22 |
24 // Max delta is 4095 milliseconds because we need to be able to encode it in | 23 // Max delta is 4095 milliseconds because we need to be able to encode it in |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 private: | 138 private: |
140 std::ostringstream stream_; | 139 std::ostringstream stream_; |
141 int frame_count_; | 140 int frame_count_; |
142 int packet_count_; | 141 int packet_count_; |
143 int last_frame_id_; | 142 int last_frame_id_; |
144 int last_packet_id_; | 143 int last_packet_id_; |
145 bool contiguous_sequence_; | 144 bool contiguous_sequence_; |
146 }; | 145 }; |
147 } // namespace | 146 } // namespace |
148 | 147 |
149 // TODO(mikhal): This is only used by the receiver. Consider renaming. | 148 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, |
150 RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment, | |
151 PacedPacketSender* outgoing_transport, | |
152 uint32 sending_ssrc, | 149 uint32 sending_ssrc, |
153 const std::string& c_name) | 150 const std::string& c_name) |
154 : ssrc_(sending_ssrc), | 151 : ssrc_(sending_ssrc), |
155 c_name_(c_name), | 152 c_name_(c_name), |
156 transport_(outgoing_transport), | 153 transport_(outgoing_transport) { |
157 cast_environment_(cast_environment) { | |
158 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; | 154 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; |
159 } | 155 } |
160 | 156 |
161 RtcpSender::~RtcpSender() {} | 157 RtcpSender::~RtcpSender() {} |
162 | 158 |
163 void RtcpSender::SendRtcpFromRtpReceiver( | 159 void RtcpSender::SendRtcpFromRtpReceiver( |
164 uint32 packet_type_flags, | 160 uint32 packet_type_flags, |
165 const RtcpReportBlock* report_block, | 161 const RtcpReportBlock* report_block, |
166 const RtcpReceiverReferenceTimeReport* rrtr, | 162 const RtcpReceiverReferenceTimeReport* rrtr, |
167 const RtcpCastMessage* cast_message, | 163 const RtcpCastMessage* cast_message, |
168 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, | 164 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, |
169 base::TimeDelta target_delay) { | 165 base::TimeDelta target_delay) { |
170 if (packet_type_flags & kRtcpSr || | 166 if (packet_type_flags & kRtcpSr || |
171 packet_type_flags & kRtcpDlrr || | 167 packet_type_flags & kRtcpDlrr || |
172 packet_type_flags & kRtcpSenderLog) { | 168 packet_type_flags & kRtcpSenderLog) { |
173 NOTREACHED() << "Invalid argument"; | 169 NOTREACHED() << "Invalid argument"; |
174 } | 170 } |
175 if (packet_type_flags & kRtcpPli || | 171 if (packet_type_flags & kRtcpPli || |
176 packet_type_flags & kRtcpRpsi || | 172 packet_type_flags & kRtcpRpsi || |
177 packet_type_flags & kRtcpRemb || | 173 packet_type_flags & kRtcpRemb || |
178 packet_type_flags & kRtcpNack) { | 174 packet_type_flags & kRtcpNack) { |
179 // Implement these for webrtc interop. | 175 // Implement these for webrtc interop. |
180 NOTIMPLEMENTED(); | 176 NOTIMPLEMENTED(); |
181 } | 177 } |
182 PacketRef packet(new base::RefCountedData<Packet>); | 178 PacketRef packet(new base::RefCountedData<Packet>); |
183 packet->data.reserve(kMaxIpPacketSize); | 179 packet->data.reserve(kMaxIpPacketSize); |
184 | |
185 if (packet_type_flags & kRtcpRr) { | 180 if (packet_type_flags & kRtcpRr) { |
186 BuildRR(report_block, &packet->data); | 181 BuildRR(report_block, &packet->data); |
187 if (!c_name_.empty()) { | 182 if (!c_name_.empty()) { |
188 BuildSdec(&packet->data); | 183 BuildSdec(&packet->data); |
189 } | 184 } |
190 } | 185 } |
191 if (packet_type_flags & kRtcpBye) { | 186 if (packet_type_flags & kRtcpBye) { |
192 BuildBye(&packet->data); | 187 BuildBye(&packet->data); |
193 } | 188 } |
194 if (packet_type_flags & kRtcpRrtr) { | 189 if (packet_type_flags & kRtcpRrtr) { |
195 DCHECK(rrtr) << "Invalid argument"; | 190 DCHECK(rrtr) << "Invalid argument"; |
196 BuildRrtr(rrtr, &packet->data); | 191 BuildRrtr(rrtr, &packet->data); |
197 } | 192 } |
198 if (packet_type_flags & kRtcpCast) { | 193 if (packet_type_flags & kRtcpCast) { |
199 DCHECK(cast_message) << "Invalid argument"; | 194 DCHECK(cast_message) << "Invalid argument"; |
200 BuildCast(cast_message, target_delay, &packet->data); | 195 BuildCast(cast_message, target_delay, &packet->data); |
201 } | 196 } |
202 if (packet_type_flags & kRtcpReceiverLog) { | 197 if (packet_type_flags & kRtcpReceiverLog) { |
203 DCHECK(rtcp_events) << "Invalid argument"; | 198 DCHECK(rtcp_events) << "Invalid argument"; |
204 BuildReceiverLog(*rtcp_events, &packet->data); | 199 BuildReceiverLog(*rtcp_events, &packet->data); |
205 } | 200 } |
206 | 201 |
207 if (packet->data.empty()) | 202 if (packet->data.empty()) { |
| 203 NOTREACHED() << "Empty packet."; |
208 return; // Sanity don't send empty packets. | 204 return; // Sanity don't send empty packets. |
| 205 } |
209 | 206 |
210 transport_->SendRtcpPacket(ssrc_, packet); | 207 transport_->SendRtcpPacket(ssrc_, packet); |
211 } | 208 } |
| 209 |
| 210 void RtcpSender::SendRtcpFromRtpSender( |
| 211 uint32 packet_type_flags, |
| 212 const RtcpSenderInfo& sender_info, |
| 213 const RtcpDlrrReportBlock& dlrr) { |
| 214 if (packet_type_flags & kRtcpRr || |
| 215 packet_type_flags & kRtcpPli || |
| 216 packet_type_flags & kRtcpRrtr || |
| 217 packet_type_flags & kRtcpCast || |
| 218 packet_type_flags & kRtcpReceiverLog || |
| 219 packet_type_flags & kRtcpRpsi || |
| 220 packet_type_flags & kRtcpRemb || |
| 221 packet_type_flags & kRtcpNack) { |
| 222 NOTREACHED() << "Invalid argument"; |
| 223 } |
| 224 PacketRef packet(new base::RefCountedData<Packet>); |
| 225 packet->data.reserve(kMaxIpPacketSize); |
| 226 if (packet_type_flags & kRtcpSr) { |
| 227 BuildSR(sender_info, &packet->data); |
| 228 BuildSdec(&packet->data); |
| 229 } |
| 230 if (packet_type_flags & kRtcpBye) { |
| 231 BuildBye(&packet->data); |
| 232 } |
| 233 if (packet_type_flags & kRtcpDlrr) { |
| 234 BuildDlrrRb(dlrr, &packet->data); |
| 235 } |
| 236 if (packet->data.empty()) { |
| 237 NOTREACHED() << "Empty packet."; |
| 238 return; // Sanity - don't send empty packets. |
| 239 } |
| 240 |
| 241 transport_->SendRtcpPacket(ssrc_, packet); |
| 242 } |
212 | 243 |
213 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, | 244 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, |
214 Packet* packet) const { | 245 Packet* packet) const { |
215 size_t start_size = packet->size(); | 246 size_t start_size = packet->size(); |
216 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space"; | 247 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space"; |
217 if (start_size + 32 > kMaxIpPacketSize) | 248 if (start_size + 32 > kMaxIpPacketSize) |
218 return; | 249 return; |
219 | 250 |
220 uint16 number_of_rows = (report_block) ? 7 : 1; | 251 uint16 number_of_rows = (report_block) ? 7 : 1; |
221 packet->resize(start_size + 8); | 252 packet->resize(start_size + 8); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 358 |
328 /* | 359 /* |
329 0 1 2 3 | 360 0 1 2 3 |
330 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 361 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
331 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 362 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
332 | PB |0| Payload Type| Native Rpsi bit string | | 363 | PB |0| Payload Type| Native Rpsi bit string | |
333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 364 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
334 | defined per codec ... | Padding (0) | | 365 | defined per codec ... | Padding (0) | |
335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 366 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
336 */ | 367 */ |
337 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const { | 368 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, |
| 369 Packet* packet) const { |
338 size_t start_size = packet->size(); | 370 size_t start_size = packet->size(); |
339 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; | 371 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; |
340 if (start_size + 24 > kMaxIpPacketSize) | 372 if (start_size + 24 > kMaxIpPacketSize) |
341 return; | 373 return; |
342 | 374 |
343 packet->resize(start_size + 24); | 375 packet->resize(start_size + 24); |
344 | 376 |
345 base::BigEndianWriter big_endian_writer( | 377 base::BigEndianWriter big_endian_writer( |
346 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | 378 reinterpret_cast<char*>(&((*packet)[start_size])), 24); |
347 uint8 FMT = 3; // Reference Picture Selection Indication. | 379 uint8 FMT = 3; // Reference Picture Selection Indication. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 } | 413 } |
382 // Add last byte of picture ID. | 414 // Add last byte of picture ID. |
383 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f)); | 415 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f)); |
384 | 416 |
385 // Add padding. | 417 // Add padding. |
386 for (int j = 0; j < padding_bytes; ++j) { | 418 for (int j = 0; j < padding_bytes; ++j) { |
387 big_endian_writer.WriteU8(0); | 419 big_endian_writer.WriteU8(0); |
388 } | 420 } |
389 } | 421 } |
390 | 422 |
391 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const { | 423 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, |
| 424 Packet* packet) const { |
392 size_t start_size = packet->size(); | 425 size_t start_size = packet->size(); |
393 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size(); | 426 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size(); |
394 DCHECK_LT(start_size + remb_size, kMaxIpPacketSize) | 427 DCHECK_LT(start_size + remb_size, kMaxIpPacketSize) |
395 << "Not enough buffer space"; | 428 << "Not enough buffer space"; |
396 if (start_size + remb_size > kMaxIpPacketSize) | 429 if (start_size + remb_size > kMaxIpPacketSize) |
397 return; | 430 return; |
398 | 431 |
399 packet->resize(start_size + remb_size); | 432 packet->resize(start_size + remb_size); |
400 | 433 |
401 base::BigEndianWriter big_endian_writer( | 434 base::BigEndianWriter big_endian_writer( |
(...skipping 20 matching lines...) Expand all Loading... |
422 (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03))); | 455 (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03))); |
423 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8)); | 456 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8)); |
424 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa)); | 457 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa)); |
425 | 458 |
426 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin(); | 459 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin(); |
427 for (; it != remb->remb_ssrcs.end(); ++it) { | 460 for (; it != remb->remb_ssrcs.end(); ++it) { |
428 big_endian_writer.WriteU32(*it); | 461 big_endian_writer.WriteU32(*it); |
429 } | 462 } |
430 } | 463 } |
431 | 464 |
432 void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const { | 465 void RtcpSender::BuildNack(const RtcpNackMessage* nack, |
| 466 Packet* packet) const { |
433 size_t start_size = packet->size(); | 467 size_t start_size = packet->size(); |
434 DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space"; | 468 DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space"; |
435 if (start_size + 16 > kMaxIpPacketSize) | 469 if (start_size + 16 > kMaxIpPacketSize) |
436 return; | 470 return; |
437 | 471 |
438 packet->resize(start_size + 16); | 472 packet->resize(start_size + 16); |
439 | 473 |
440 base::BigEndianWriter big_endian_writer( | 474 base::BigEndianWriter big_endian_writer( |
441 reinterpret_cast<char*>(&((*packet)[start_size])), 16); | 475 reinterpret_cast<char*>(&((*packet)[start_size])), 16); |
442 | 476 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 | 574 |
541 base::BigEndianWriter big_endian_writer( | 575 base::BigEndianWriter big_endian_writer( |
542 reinterpret_cast<char*>(&((*packet)[start_size])), 20); | 576 reinterpret_cast<char*>(&((*packet)[start_size])), 20); |
543 uint8 FMT = 15; // Application layer feedback. | 577 uint8 FMT = 15; // Application layer feedback. |
544 big_endian_writer.WriteU8(0x80 + FMT); | 578 big_endian_writer.WriteU8(0x80 + FMT); |
545 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | 579 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); |
546 big_endian_writer.WriteU8(0); | 580 big_endian_writer.WriteU8(0); |
547 size_t cast_size_pos = start_size + 3; // Save length position. | 581 size_t cast_size_pos = start_size + 3; // Save length position. |
548 big_endian_writer.WriteU8(4); | 582 big_endian_writer.WriteU8(4); |
549 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | 583 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
550 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC. | 584 big_endian_writer.WriteU32(cast->media_ssrc); // Remote SSRC. |
551 big_endian_writer.WriteU32(kCast); | 585 big_endian_writer.WriteU32(kCast); |
552 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_)); | 586 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id)); |
553 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. | 587 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. |
554 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. | 588 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. |
555 DCHECK_LE(target_delay.InMilliseconds(), | 589 DCHECK_LE(target_delay.InMilliseconds(), |
556 std::numeric_limits<uint16_t>::max()); | 590 std::numeric_limits<uint16_t>::max()); |
557 big_endian_writer.WriteU16(target_delay.InMilliseconds()); | 591 big_endian_writer.WriteU16(target_delay.InMilliseconds()); |
558 | 592 |
559 size_t number_of_loss_fields = 0; | 593 size_t number_of_loss_fields = 0; |
560 size_t max_number_of_loss_fields = std::min<size_t>( | 594 size_t max_number_of_loss_fields = std::min<size_t>( |
561 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4); | 595 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4); |
562 | 596 |
563 MissingFramesAndPacketsMap::const_iterator frame_it = | 597 MissingFramesAndPacketsMap::const_iterator frame_it = |
564 cast->missing_frames_and_packets_.begin(); | 598 cast->missing_frames_and_packets.begin(); |
565 | 599 |
566 NackStringBuilder nack_string_builder; | 600 NackStringBuilder nack_string_builder; |
567 for (; frame_it != cast->missing_frames_and_packets_.end() && | 601 for (; frame_it != cast->missing_frames_and_packets.end() && |
568 number_of_loss_fields < max_number_of_loss_fields; | 602 number_of_loss_fields < max_number_of_loss_fields; |
569 ++frame_it) { | 603 ++frame_it) { |
570 nack_string_builder.PushFrame(frame_it->first); | 604 nack_string_builder.PushFrame(frame_it->first); |
571 // Iterate through all frames with missing packets. | 605 // Iterate through all frames with missing packets. |
572 if (frame_it->second.empty()) { | 606 if (frame_it->second.empty()) { |
573 // Special case all packets in a frame is missing. | 607 // Special case all packets in a frame is missing. |
574 start_size = packet->size(); | 608 start_size = packet->size(); |
575 packet->resize(start_size + 4); | 609 packet->resize(start_size + 4); |
576 base::BigEndianWriter big_endian_nack_writer( | 610 base::BigEndianWriter big_endian_nack_writer( |
577 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | 611 reinterpret_cast<char*>(&((*packet)[start_size])), 4); |
(...skipping 28 matching lines...) Expand all Loading... |
606 } else { | 640 } else { |
607 break; | 641 break; |
608 } | 642 } |
609 } | 643 } |
610 big_endian_nack_writer.WriteU8(bitmask); | 644 big_endian_nack_writer.WriteU8(bitmask); |
611 ++number_of_loss_fields; | 645 ++number_of_loss_fields; |
612 } | 646 } |
613 } | 647 } |
614 } | 648 } |
615 VLOG_IF(1, !nack_string_builder.Empty()) | 649 VLOG_IF(1, !nack_string_builder.Empty()) |
616 << "SSRC: " << cast->media_ssrc_ | 650 << "SSRC: " << cast->media_ssrc |
617 << ", ACK: " << cast->ack_frame_id_ | 651 << ", ACK: " << cast->ack_frame_id |
618 << ", NACK: " << nack_string_builder.GetString(); | 652 << ", NACK: " << nack_string_builder.GetString(); |
619 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); | 653 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); |
620 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); | 654 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); |
621 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); | 655 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); |
622 } | 656 } |
623 | 657 |
| 658 void RtcpSender::BuildSR(const RtcpSenderInfo& sender_info, |
| 659 Packet* packet) const { |
| 660 // Sender report. |
| 661 size_t start_size = packet->size(); |
| 662 if (start_size + 52 > kMaxIpPacketSize) { |
| 663 DLOG(FATAL) << "Not enough buffer space"; |
| 664 return; |
| 665 } |
| 666 |
| 667 uint16 number_of_rows = 6; |
| 668 packet->resize(start_size + 28); |
| 669 |
| 670 base::BigEndianWriter big_endian_writer( |
| 671 reinterpret_cast<char*>(&((*packet)[start_size])), 28); |
| 672 big_endian_writer.WriteU8(0x80); |
| 673 big_endian_writer.WriteU8(kPacketTypeSenderReport); |
| 674 big_endian_writer.WriteU16(number_of_rows); |
| 675 big_endian_writer.WriteU32(ssrc_); |
| 676 big_endian_writer.WriteU32(sender_info.ntp_seconds); |
| 677 big_endian_writer.WriteU32(sender_info.ntp_fraction); |
| 678 big_endian_writer.WriteU32(sender_info.rtp_timestamp); |
| 679 big_endian_writer.WriteU32(sender_info.send_packet_count); |
| 680 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); |
| 681 return; |
| 682 } |
| 683 |
| 684 /* |
| 685 0 1 2 3 |
| 686 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 |
| 687 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 688 |V=2|P|reserved | PT=XR=207 | length | |
| 689 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 690 | SSRC | |
| 691 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 692 | BT=5 | reserved | block length | |
| 693 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| 694 | SSRC1 (SSRC of first receiver) | sub- |
| 695 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block |
| 696 | last RR (LRR) | 1 |
| 697 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 698 | delay since last RR (DLRR) | |
| 699 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| 700 */ |
| 701 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, |
| 702 Packet* packet) const { |
| 703 size_t start_size = packet->size(); |
| 704 if (start_size + 24 > kMaxIpPacketSize) { |
| 705 DLOG(FATAL) << "Not enough buffer space"; |
| 706 return; |
| 707 } |
| 708 |
| 709 packet->resize(start_size + 24); |
| 710 |
| 711 base::BigEndianWriter big_endian_writer( |
| 712 reinterpret_cast<char*>(&((*packet)[start_size])), 24); |
| 713 big_endian_writer.WriteU8(0x80); |
| 714 big_endian_writer.WriteU8(kPacketTypeXr); |
| 715 big_endian_writer.WriteU16(5); // Length. |
| 716 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. |
| 717 big_endian_writer.WriteU8(5); // Add block type. |
| 718 big_endian_writer.WriteU8(0); // Add reserved. |
| 719 big_endian_writer.WriteU16(3); // Block length. |
| 720 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. |
| 721 big_endian_writer.WriteU32(dlrr.last_rr); |
| 722 big_endian_writer.WriteU32(dlrr.delay_since_last_rr); |
| 723 return; |
| 724 } |
| 725 |
624 void RtcpSender::BuildReceiverLog( | 726 void RtcpSender::BuildReceiverLog( |
625 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, | 727 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, |
626 Packet* packet) { | 728 Packet* packet) { |
627 const size_t packet_start_size = packet->size(); | 729 const size_t packet_start_size = packet->size(); |
628 size_t number_of_frames = 0; | 730 size_t number_of_frames = 0; |
629 size_t total_number_of_messages_to_send = 0; | 731 size_t total_number_of_messages_to_send = 0; |
630 size_t rtcp_log_size = 0; | 732 size_t rtcp_log_size = 0; |
631 RtcpReceiverLogMessage receiver_log_message; | 733 RtcpReceiverLogMessage receiver_log_message; |
632 | 734 |
633 if (!BuildRtcpReceiverLogMessage(rtcp_events, | 735 if (!BuildRtcpReceiverLogMessage(rtcp_events, |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 << "Not enough buffer space."; | 920 << "Not enough buffer space."; |
819 | 921 |
820 VLOG(3) << "number of frames: " << *number_of_frames; | 922 VLOG(3) << "number of frames: " << *number_of_frames; |
821 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; | 923 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; |
822 VLOG(3) << "rtcp log size: " << *rtcp_log_size; | 924 VLOG(3) << "rtcp log size: " << *rtcp_log_size; |
823 return *number_of_frames > 0; | 925 return *number_of_frames > 0; |
824 } | 926 } |
825 | 927 |
826 } // namespace cast | 928 } // namespace cast |
827 } // namespace media | 929 } // namespace media |
OLD | NEW |