1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cast/rtcp/rtcp_sender.h"
12 #include "base/big_endian.h"
13 #include "base/logging.h"
14 #include "media/cast/cast_environment.h"
15 #include "media/cast/rtcp/rtcp_defines.h"
16 #include "media/cast/rtcp/rtcp_utility.h"
17 #include "media/cast/transport/cast_transport_defines.h"
18 #include "media/cast/transport/pacing/paced_sender.h"
24 // Max delta is 4095 milliseconds because we need to be able to encode it in
26 const int64 kMaxWireFormatTimeDeltaMs
= INT64_C(0xfff);
28 uint16
MergeEventTypeAndTimestampForWireFormat(
29 const CastLoggingEvent
& event
,
30 const base::TimeDelta
& time_delta
) {
31 int64 time_delta_ms
= time_delta
.InMilliseconds();
33 DCHECK_GE(time_delta_ms
, 0);
34 DCHECK_LE(time_delta_ms
, kMaxWireFormatTimeDeltaMs
);
36 uint16 time_delta_12_bits
=
37 static_cast<uint16
>(time_delta_ms
& kMaxWireFormatTimeDeltaMs
);
39 uint16 event_type_4_bits
= ConvertEventTypeToWireFormat(event
);
40 DCHECK(event_type_4_bits
);
41 DCHECK(~(event_type_4_bits
& 0xfff0));
42 return (event_type_4_bits
<< 12) | time_delta_12_bits
;
45 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage
& lhs
,
46 const RtcpReceiverEventLogMessage
& rhs
) {
47 return lhs
.event_timestamp
< rhs
.event_timestamp
;
51 const RtcpReceiverLogMessage
& redundancy_receiver_log_message
,
52 RtcpReceiverLogMessage
* receiver_log_message
,
53 size_t* remaining_space
,
54 size_t* number_of_frames
,
55 size_t* total_number_of_messages_to_send
) {
56 RtcpReceiverLogMessage::const_iterator it
=
57 redundancy_receiver_log_message
.begin();
58 while (it
!= redundancy_receiver_log_message
.end() &&
60 kRtcpReceiverFrameLogSize
+ kRtcpReceiverEventLogSize
) {
61 receiver_log_message
->push_front(*it
);
62 size_t num_event_logs
= (*remaining_space
- kRtcpReceiverFrameLogSize
) /
63 kRtcpReceiverEventLogSize
;
64 RtcpReceiverEventLogMessages
& event_log_messages
=
65 receiver_log_message
->front().event_log_messages_
;
66 if (num_event_logs
< event_log_messages
.size())
67 event_log_messages
.resize(num_event_logs
);
69 *remaining_space
-= kRtcpReceiverFrameLogSize
+
70 event_log_messages
.size() * kRtcpReceiverEventLogSize
;
72 *total_number_of_messages_to_send
+= event_log_messages
.size();
77 // A class to build a string representing the NACK list in Cast message.
79 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame
80 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of
81 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
82 // completely missing will show as "26:65535".
83 class NackStringBuilder
{
90 contiguous_sequence_(false) {}
91 ~NackStringBuilder() {}
93 bool Empty() const { return frame_count_
== 0; }
95 void PushFrame(int frame_id
) {
96 DCHECK_GE(frame_id
, 0);
97 if (frame_count_
> 0) {
98 if (frame_id
== last_frame_id_
) {
101 if (contiguous_sequence_
) {
102 stream_
<< "-" << last_packet_id_
;
107 last_frame_id_
= frame_id
;
109 contiguous_sequence_
= false;
113 void PushPacket(int packet_id
) {
114 DCHECK_GE(last_frame_id_
, 0);
115 DCHECK_GE(packet_id
, 0);
116 if (packet_count_
== 0) {
117 stream_
<< ":" << packet_id
;
118 } else if (packet_id
== last_packet_id_
+ 1) {
119 contiguous_sequence_
= true;
121 if (contiguous_sequence_
) {
122 stream_
<< "-" << last_packet_id_
;
123 contiguous_sequence_
= false;
125 stream_
<< "," << packet_id
;
128 last_packet_id_
= packet_id
;
131 std::string
GetString() {
132 if (contiguous_sequence_
) {
133 stream_
<< "-" << last_packet_id_
;
134 contiguous_sequence_
= false;
136 return stream_
.str();
140 std::ostringstream stream_
;
145 bool contiguous_sequence_
;
149 // TODO(mikhal): This is only used by the receiver. Consider renaming.
150 RtcpSender::RtcpSender(scoped_refptr
<CastEnvironment
> cast_environment
,
151 transport::PacedPacketSender
* outgoing_transport
,
153 const std::string
& c_name
)
154 : ssrc_(sending_ssrc
),
156 transport_(outgoing_transport
),
157 cast_environment_(cast_environment
) {
158 DCHECK_LT(c_name_
.length(), kRtcpCnameSize
) << "Invalid config";
161 RtcpSender::~RtcpSender() {}
163 void RtcpSender::SendRtcpFromRtpReceiver(
164 uint32 packet_type_flags
,
165 const transport::RtcpReportBlock
* report_block
,
166 const RtcpReceiverReferenceTimeReport
* rrtr
,
167 const RtcpCastMessage
* cast_message
,
168 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap
* rtcp_events
,
169 uint16 target_delay_ms
) {
170 if (packet_type_flags
& transport::kRtcpSr
||
171 packet_type_flags
& transport::kRtcpDlrr
||
172 packet_type_flags
& transport::kRtcpSenderLog
) {
173 NOTREACHED() << "Invalid argument";
175 if (packet_type_flags
& transport::kRtcpPli
||
176 packet_type_flags
& transport::kRtcpRpsi
||
177 packet_type_flags
& transport::kRtcpRemb
||
178 packet_type_flags
& transport::kRtcpNack
) {
179 // Implement these for webrtc interop.
182 transport::PacketRef
packet(new base::RefCountedData
<Packet
>);
183 packet
->data
.reserve(kMaxIpPacketSize
);
185 if (packet_type_flags
& transport::kRtcpRr
) {
186 BuildRR(report_block
, &packet
->data
);
187 if (!c_name_
.empty()) {
188 BuildSdec(&packet
->data
);
191 if (packet_type_flags
& transport::kRtcpBye
) {
192 BuildBye(&packet
->data
);
194 if (packet_type_flags
& transport::kRtcpRrtr
) {
195 DCHECK(rrtr
) << "Invalid argument";
196 BuildRrtr(rrtr
, &packet
->data
);
198 if (packet_type_flags
& transport::kRtcpCast
) {
199 DCHECK(cast_message
) << "Invalid argument";
200 BuildCast(cast_message
, target_delay_ms
, &packet
->data
);
202 if (packet_type_flags
& transport::kRtcpReceiverLog
) {
203 DCHECK(rtcp_events
) << "Invalid argument";
204 BuildReceiverLog(*rtcp_events
, &packet
->data
);
207 if (packet
->data
.empty())
208 return; // Sanity don't send empty packets.
210 transport_
->SendRtcpPacket(ssrc_
, packet
);
213 void RtcpSender::BuildRR(const transport::RtcpReportBlock
* report_block
,
214 Packet
* packet
) const {
215 size_t start_size
= packet
->size();
216 DCHECK_LT(start_size
+ 32, kMaxIpPacketSize
) << "Not enough buffer space";
217 if (start_size
+ 32 > kMaxIpPacketSize
)
220 uint16 number_of_rows
= (report_block
) ? 7 : 1;
221 packet
->resize(start_size
+ 8);
223 base::BigEndianWriter
big_endian_writer(
224 reinterpret_cast<char*>(&((*packet
)[start_size
])), 8);
225 big_endian_writer
.WriteU8(0x80 + (report_block
? 1 : 0));
226 big_endian_writer
.WriteU8(transport::kPacketTypeReceiverReport
);
227 big_endian_writer
.WriteU16(number_of_rows
);
228 big_endian_writer
.WriteU32(ssrc_
);
231 AddReportBlocks(*report_block
, packet
); // Adds 24 bytes.
235 void RtcpSender::AddReportBlocks(const transport::RtcpReportBlock
& report_block
,
236 Packet
* packet
) const {
237 size_t start_size
= packet
->size();
238 DCHECK_LT(start_size
+ 24, kMaxIpPacketSize
) << "Not enough buffer space";
239 if (start_size
+ 24 > kMaxIpPacketSize
)
242 packet
->resize(start_size
+ 24);
244 base::BigEndianWriter
big_endian_writer(
245 reinterpret_cast<char*>(&((*packet
)[start_size
])), 24);
246 big_endian_writer
.WriteU32(report_block
.media_ssrc
);
247 big_endian_writer
.WriteU8(report_block
.fraction_lost
);
248 big_endian_writer
.WriteU8(report_block
.cumulative_lost
>> 16);
249 big_endian_writer
.WriteU8(report_block
.cumulative_lost
>> 8);
250 big_endian_writer
.WriteU8(report_block
.cumulative_lost
);
252 // Extended highest seq_no, contain the highest sequence number received.
253 big_endian_writer
.WriteU32(report_block
.extended_high_sequence_number
);
254 big_endian_writer
.WriteU32(report_block
.jitter
);
256 // Last SR timestamp; our NTP time when we received the last report.
257 // This is the value that we read from the send report packet not when we
259 big_endian_writer
.WriteU32(report_block
.last_sr
);
261 // Delay since last received report, time since we received the report.
262 big_endian_writer
.WriteU32(report_block
.delay_since_last_sr
);
265 void RtcpSender::BuildSdec(Packet
* packet
) const {
266 size_t start_size
= packet
->size();
267 DCHECK_LT(start_size
+ 12 + c_name_
.length(), kMaxIpPacketSize
)
268 << "Not enough buffer space";
269 if (start_size
+ 12 > kMaxIpPacketSize
)
272 // SDES Source Description.
273 packet
->resize(start_size
+ 10);
275 base::BigEndianWriter
big_endian_writer(
276 reinterpret_cast<char*>(&((*packet
)[start_size
])), 10);
277 // We always need to add one SDES CNAME.
278 big_endian_writer
.WriteU8(0x80 + 1);
279 big_endian_writer
.WriteU8(transport::kPacketTypeSdes
);
281 // Handle SDES length later on.
282 uint32 sdes_length_position
= static_cast<uint32
>(start_size
) + 3;
283 big_endian_writer
.WriteU16(0);
284 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
285 big_endian_writer
.WriteU8(1); // CNAME = 1
286 big_endian_writer
.WriteU8(static_cast<uint8
>(c_name_
.length()));
288 size_t sdes_length
= 10 + c_name_
.length();
290 packet
->end(), c_name_
.c_str(), c_name_
.c_str() + c_name_
.length());
294 // We must have a zero field even if we have an even multiple of 4 bytes.
295 if ((packet
->size() % 4) == 0) {
297 packet
->push_back(0);
299 while ((packet
->size() % 4) != 0) {
301 packet
->push_back(0);
303 sdes_length
+= padding
;
305 // In 32-bit words minus one and we don't count the header.
306 uint8 buffer_length
= static_cast<uint8
>((sdes_length
/ 4) - 1);
307 (*packet
)[sdes_length_position
] = buffer_length
;
310 void RtcpSender::BuildPli(uint32 remote_ssrc
, Packet
* packet
) const {
311 size_t start_size
= packet
->size();
312 DCHECK_LT(start_size
+ 12, kMaxIpPacketSize
) << "Not enough buffer space";
313 if (start_size
+ 12 > kMaxIpPacketSize
)
316 packet
->resize(start_size
+ 12);
318 base::BigEndianWriter
big_endian_writer(
319 reinterpret_cast<char*>(&((*packet
)[start_size
])), 12);
320 uint8 FMT
= 1; // Picture loss indicator.
321 big_endian_writer
.WriteU8(0x80 + FMT
);
322 big_endian_writer
.WriteU8(transport::kPacketTypePayloadSpecific
);
323 big_endian_writer
.WriteU16(2); // Used fixed length of 2.
324 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
325 big_endian_writer
.WriteU32(remote_ssrc
); // Add the remote SSRC.
330 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
331 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
332 | PB |0| Payload Type| Native Rpsi bit string |
333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334 | defined per codec ... | Padding (0) |
335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
337 void RtcpSender::BuildRpsi(const RtcpRpsiMessage
* rpsi
, Packet
* packet
) const {
338 size_t start_size
= packet
->size();
339 DCHECK_LT(start_size
+ 24, kMaxIpPacketSize
) << "Not enough buffer space";
340 if (start_size
+ 24 > kMaxIpPacketSize
)
343 packet
->resize(start_size
+ 24);
345 base::BigEndianWriter
big_endian_writer(
346 reinterpret_cast<char*>(&((*packet
)[start_size
])), 24);
347 uint8 FMT
= 3; // Reference Picture Selection Indication.
348 big_endian_writer
.WriteU8(0x80 + FMT
);
349 big_endian_writer
.WriteU8(transport::kPacketTypePayloadSpecific
);
352 uint32 bits_required
= 7;
353 uint8 bytes_required
= 1;
354 while ((rpsi
->picture_id
>> bits_required
) > 0) {
359 if (bytes_required
> 6) {
361 } else if (bytes_required
> 2) {
364 big_endian_writer
.WriteU8(0);
365 big_endian_writer
.WriteU8(size
);
366 big_endian_writer
.WriteU32(ssrc_
);
367 big_endian_writer
.WriteU32(rpsi
->remote_ssrc
);
369 uint8 padding_bytes
= 4 - ((2 + bytes_required
) % 4);
370 if (padding_bytes
== 4) {
373 // Add padding length in bits, padding can be 0, 8, 16 or 24.
374 big_endian_writer
.WriteU8(padding_bytes
* 8);
375 big_endian_writer
.WriteU8(rpsi
->payload_type
);
378 for (int i
= bytes_required
- 1; i
> 0; i
--) {
379 big_endian_writer
.WriteU8(0x80 |
380 static_cast<uint8
>(rpsi
->picture_id
>> (i
* 7)));
382 // Add last byte of picture ID.
383 big_endian_writer
.WriteU8(static_cast<uint8
>(rpsi
->picture_id
& 0x7f));
386 for (int j
= 0; j
< padding_bytes
; ++j
) {
387 big_endian_writer
.WriteU8(0);
391 void RtcpSender::BuildRemb(const RtcpRembMessage
* remb
, Packet
* packet
) const {
392 size_t start_size
= packet
->size();
393 size_t remb_size
= 20 + 4 * remb
->remb_ssrcs
.size();
394 DCHECK_LT(start_size
+ remb_size
, kMaxIpPacketSize
)
395 << "Not enough buffer space";
396 if (start_size
+ remb_size
> kMaxIpPacketSize
)
399 packet
->resize(start_size
+ remb_size
);
401 base::BigEndianWriter
big_endian_writer(
402 reinterpret_cast<char*>(&((*packet
)[start_size
])), remb_size
);
404 // Add application layer feedback.
406 big_endian_writer
.WriteU8(0x80 + FMT
);
407 big_endian_writer
.WriteU8(transport::kPacketTypePayloadSpecific
);
408 big_endian_writer
.WriteU8(0);
409 big_endian_writer
.WriteU8(static_cast<uint8
>(remb
->remb_ssrcs
.size() + 4));
410 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
411 big_endian_writer
.WriteU32(0); // Remote SSRC must be 0.
412 big_endian_writer
.WriteU32(kRemb
);
413 big_endian_writer
.WriteU8(static_cast<uint8
>(remb
->remb_ssrcs
.size()));
415 // 6 bit exponent and a 18 bit mantissa.
416 uint8 bitrate_exponent
;
417 uint32 bitrate_mantissa
;
418 BitrateToRembExponentBitrate(
419 remb
->remb_bitrate
, &bitrate_exponent
, &bitrate_mantissa
);
421 big_endian_writer
.WriteU8(static_cast<uint8
>(
422 (bitrate_exponent
<< 2) + ((bitrate_mantissa
>> 16) & 0x03)));
423 big_endian_writer
.WriteU8(static_cast<uint8
>(bitrate_mantissa
>> 8));
424 big_endian_writer
.WriteU8(static_cast<uint8
>(bitrate_mantissa
));
426 std::list
<uint32
>::const_iterator it
= remb
->remb_ssrcs
.begin();
427 for (; it
!= remb
->remb_ssrcs
.end(); ++it
) {
428 big_endian_writer
.WriteU32(*it
);
432 void RtcpSender::BuildNack(const RtcpNackMessage
* nack
, Packet
* packet
) const {
433 size_t start_size
= packet
->size();
434 DCHECK_LT(start_size
+ 16, kMaxIpPacketSize
) << "Not enough buffer space";
435 if (start_size
+ 16 > kMaxIpPacketSize
)
438 packet
->resize(start_size
+ 16);
440 base::BigEndianWriter
big_endian_writer(
441 reinterpret_cast<char*>(&((*packet
)[start_size
])), 16);
444 big_endian_writer
.WriteU8(0x80 + FMT
);
445 big_endian_writer
.WriteU8(transport::kPacketTypeGenericRtpFeedback
);
446 big_endian_writer
.WriteU8(0);
447 size_t nack_size_pos
= start_size
+ 3;
448 big_endian_writer
.WriteU8(3);
449 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
450 big_endian_writer
.WriteU32(nack
->remote_ssrc
); // Add the remote SSRC.
452 // Build NACK bitmasks and write them to the Rtcp message.
453 // The nack list should be sorted and not contain duplicates.
454 size_t number_of_nack_fields
= 0;
455 size_t max_number_of_nack_fields
= std::min
<size_t>(
456 kRtcpMaxNackFields
, (kMaxIpPacketSize
- packet
->size()) / 4);
458 std::list
<uint16
>::const_iterator it
= nack
->nack_list
.begin();
459 while (it
!= nack
->nack_list
.end() &&
460 number_of_nack_fields
< max_number_of_nack_fields
) {
461 uint16 nack_sequence_number
= *it
;
464 while (it
!= nack
->nack_list
.end()) {
465 int shift
= static_cast<uint16
>(*it
- nack_sequence_number
) - 1;
466 if (shift
>= 0 && shift
<= 15) {
467 bitmask
|= (1 << shift
);
473 // Write the sequence number and the bitmask to the packet.
474 start_size
= packet
->size();
475 DCHECK_LT(start_size
+ 4, kMaxIpPacketSize
) << "Not enough buffer space";
476 if (start_size
+ 4 > kMaxIpPacketSize
)
479 packet
->resize(start_size
+ 4);
480 base::BigEndianWriter
big_endian_nack_writer(
481 reinterpret_cast<char*>(&((*packet
)[start_size
])), 4);
482 big_endian_nack_writer
.WriteU16(nack_sequence_number
);
483 big_endian_nack_writer
.WriteU16(bitmask
);
484 number_of_nack_fields
++;
486 DCHECK_GE(kRtcpMaxNackFields
, number_of_nack_fields
);
487 (*packet
)[nack_size_pos
] = static_cast<uint8
>(2 + number_of_nack_fields
);
490 void RtcpSender::BuildBye(Packet
* packet
) const {
491 size_t start_size
= packet
->size();
492 DCHECK_LT(start_size
+ 8, kMaxIpPacketSize
) << "Not enough buffer space";
493 if (start_size
+ 8 > kMaxIpPacketSize
)
496 packet
->resize(start_size
+ 8);
498 base::BigEndianWriter
big_endian_writer(
499 reinterpret_cast<char*>(&((*packet
)[start_size
])), 8);
500 big_endian_writer
.WriteU8(0x80 + 1);
501 big_endian_writer
.WriteU8(transport::kPacketTypeBye
);
502 big_endian_writer
.WriteU16(1); // Length.
503 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
506 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport
* rrtr
,
507 Packet
* packet
) const {
508 size_t start_size
= packet
->size();
509 DCHECK_LT(start_size
+ 20, kMaxIpPacketSize
) << "Not enough buffer space";
510 if (start_size
+ 20 > kMaxIpPacketSize
)
513 packet
->resize(start_size
+ 20);
515 base::BigEndianWriter
big_endian_writer(
516 reinterpret_cast<char*>(&((*packet
)[start_size
])), 20);
518 big_endian_writer
.WriteU8(0x80);
519 big_endian_writer
.WriteU8(transport::kPacketTypeXr
);
520 big_endian_writer
.WriteU16(4); // Length.
521 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
522 big_endian_writer
.WriteU8(4); // Add block type.
523 big_endian_writer
.WriteU8(0); // Add reserved.
524 big_endian_writer
.WriteU16(2); // Block length.
526 // Add the media (received RTP) SSRC.
527 big_endian_writer
.WriteU32(rrtr
->ntp_seconds
);
528 big_endian_writer
.WriteU32(rrtr
->ntp_fraction
);
531 void RtcpSender::BuildCast(const RtcpCastMessage
* cast
,
532 uint16 target_delay_ms
,
533 Packet
* packet
) const {
534 size_t start_size
= packet
->size();
535 DCHECK_LT(start_size
+ 20, kMaxIpPacketSize
) << "Not enough buffer space";
536 if (start_size
+ 20 > kMaxIpPacketSize
)
539 packet
->resize(start_size
+ 20);
541 base::BigEndianWriter
big_endian_writer(
542 reinterpret_cast<char*>(&((*packet
)[start_size
])), 20);
543 uint8 FMT
= 15; // Application layer feedback.
544 big_endian_writer
.WriteU8(0x80 + FMT
);
545 big_endian_writer
.WriteU8(transport::kPacketTypePayloadSpecific
);
546 big_endian_writer
.WriteU8(0);
547 size_t cast_size_pos
= start_size
+ 3; // Save length position.
548 big_endian_writer
.WriteU8(4);
549 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
550 big_endian_writer
.WriteU32(cast
->media_ssrc_
); // Remote SSRC.
551 big_endian_writer
.WriteU32(kCast
);
552 big_endian_writer
.WriteU8(static_cast<uint8
>(cast
->ack_frame_id_
));
553 size_t cast_loss_field_pos
= start_size
+ 17; // Save loss field position.
554 big_endian_writer
.WriteU8(0); // Overwritten with number_of_loss_fields.
555 big_endian_writer
.WriteU16(target_delay_ms
);
557 size_t number_of_loss_fields
= 0;
558 size_t max_number_of_loss_fields
= std::min
<size_t>(
559 kRtcpMaxCastLossFields
, (kMaxIpPacketSize
- packet
->size()) / 4);
561 MissingFramesAndPacketsMap::const_iterator frame_it
=
562 cast
->missing_frames_and_packets_
.begin();
564 NackStringBuilder nack_string_builder
;
565 for (; frame_it
!= cast
->missing_frames_and_packets_
.end() &&
566 number_of_loss_fields
< max_number_of_loss_fields
;
568 nack_string_builder
.PushFrame(frame_it
->first
);
569 // Iterate through all frames with missing packets.
570 if (frame_it
->second
.empty()) {
571 // Special case all packets in a frame is missing.
572 start_size
= packet
->size();
573 packet
->resize(start_size
+ 4);
574 base::BigEndianWriter
big_endian_nack_writer(
575 reinterpret_cast<char*>(&((*packet
)[start_size
])), 4);
576 big_endian_nack_writer
.WriteU8(static_cast<uint8
>(frame_it
->first
));
577 big_endian_nack_writer
.WriteU16(kRtcpCastAllPacketsLost
);
578 big_endian_nack_writer
.WriteU8(0);
579 nack_string_builder
.PushPacket(kRtcpCastAllPacketsLost
);
580 ++number_of_loss_fields
;
582 PacketIdSet::const_iterator packet_it
= frame_it
->second
.begin();
583 while (packet_it
!= frame_it
->second
.end()) {
584 uint16 packet_id
= *packet_it
;
586 start_size
= packet
->size();
587 packet
->resize(start_size
+ 4);
588 base::BigEndianWriter
big_endian_nack_writer(
589 reinterpret_cast<char*>(&((*packet
)[start_size
])), 4);
591 // Write frame and packet id to buffer before calculating bitmask.
592 big_endian_nack_writer
.WriteU8(static_cast<uint8
>(frame_it
->first
));
593 big_endian_nack_writer
.WriteU16(packet_id
);
594 nack_string_builder
.PushPacket(packet_id
);
598 while (packet_it
!= frame_it
->second
.end()) {
599 int shift
= static_cast<uint8
>(*packet_it
- packet_id
) - 1;
600 if (shift
>= 0 && shift
<= 7) {
601 nack_string_builder
.PushPacket(*packet_it
);
602 bitmask
|= (1 << shift
);
608 big_endian_nack_writer
.WriteU8(bitmask
);
609 ++number_of_loss_fields
;
613 VLOG_IF(1, !nack_string_builder
.Empty())
614 << "SSRC: " << cast
->media_ssrc_
615 << ", ACK: " << cast
->ack_frame_id_
616 << ", NACK: " << nack_string_builder
.GetString();
617 DCHECK_LE(number_of_loss_fields
, kRtcpMaxCastLossFields
);
618 (*packet
)[cast_size_pos
] = static_cast<uint8
>(4 + number_of_loss_fields
);
619 (*packet
)[cast_loss_field_pos
] = static_cast<uint8
>(number_of_loss_fields
);
622 void RtcpSender::BuildReceiverLog(
623 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap
& rtcp_events
,
625 const size_t packet_start_size
= packet
->size();
626 size_t number_of_frames
= 0;
627 size_t total_number_of_messages_to_send
= 0;
628 size_t rtcp_log_size
= 0;
629 RtcpReceiverLogMessage receiver_log_message
;
631 if (!BuildRtcpReceiverLogMessage(rtcp_events
,
633 &receiver_log_message
,
635 &total_number_of_messages_to_send
,
639 packet
->resize(packet_start_size
+ rtcp_log_size
);
641 base::BigEndianWriter
big_endian_writer(
642 reinterpret_cast<char*>(&((*packet
)[packet_start_size
])), rtcp_log_size
);
643 big_endian_writer
.WriteU8(0x80 + kReceiverLogSubtype
);
644 big_endian_writer
.WriteU8(transport::kPacketTypeApplicationDefined
);
645 big_endian_writer
.WriteU16(static_cast<uint16
>(
646 2 + 2 * number_of_frames
+ total_number_of_messages_to_send
));
647 big_endian_writer
.WriteU32(ssrc_
); // Add our own SSRC.
648 big_endian_writer
.WriteU32(kCast
);
650 while (!receiver_log_message
.empty() &&
651 total_number_of_messages_to_send
> 0) {
652 RtcpReceiverFrameLogMessage
& frame_log_messages(
653 receiver_log_message
.front());
655 // Add our frame header.
656 big_endian_writer
.WriteU32(frame_log_messages
.rtp_timestamp_
);
657 size_t messages_in_frame
= frame_log_messages
.event_log_messages_
.size();
658 if (messages_in_frame
> total_number_of_messages_to_send
) {
659 // We are running out of space.
660 messages_in_frame
= total_number_of_messages_to_send
;
662 // Keep track of how many messages we have left to send.
663 total_number_of_messages_to_send
-= messages_in_frame
;
665 // On the wire format is number of messages - 1.
666 big_endian_writer
.WriteU8(static_cast<uint8
>(messages_in_frame
- 1));
668 base::TimeTicks event_timestamp_base
=
669 frame_log_messages
.event_log_messages_
.front().event_timestamp
;
670 uint32 base_timestamp_ms
=
671 (event_timestamp_base
- base::TimeTicks()).InMilliseconds();
672 big_endian_writer
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 16));
673 big_endian_writer
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 8));
674 big_endian_writer
.WriteU8(static_cast<uint8
>(base_timestamp_ms
));
676 while (!frame_log_messages
.event_log_messages_
.empty() &&
677 messages_in_frame
> 0) {
678 const RtcpReceiverEventLogMessage
& event_message
=
679 frame_log_messages
.event_log_messages_
.front();
680 uint16 event_type_and_timestamp_delta
=
681 MergeEventTypeAndTimestampForWireFormat(
683 event_message
.event_timestamp
- event_timestamp_base
);
684 switch (event_message
.type
) {
688 big_endian_writer
.WriteU16(
689 static_cast<uint16
>(event_message
.delay_delta
.InMilliseconds()));
690 big_endian_writer
.WriteU16(event_type_and_timestamp_delta
);
692 case PACKET_RECEIVED
:
693 big_endian_writer
.WriteU16(event_message
.packet_id
);
694 big_endian_writer
.WriteU16(event_type_and_timestamp_delta
);
700 frame_log_messages
.event_log_messages_
.pop_front();
702 if (frame_log_messages
.event_log_messages_
.empty()) {
703 // We sent all messages on this frame; pop the frame header.
704 receiver_log_message
.pop_front();
707 DCHECK_EQ(total_number_of_messages_to_send
, 0u);
710 bool RtcpSender::BuildRtcpReceiverLogMessage(
711 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap
& rtcp_events
,
713 RtcpReceiverLogMessage
* receiver_log_message
,
714 size_t* number_of_frames
,
715 size_t* total_number_of_messages_to_send
,
716 size_t* rtcp_log_size
) {
717 size_t remaining_space
=
718 std::min(kMaxReceiverLogBytes
, kMaxIpPacketSize
- start_size
);
719 if (remaining_space
< kRtcpCastLogHeaderSize
+ kRtcpReceiverFrameLogSize
+
720 kRtcpReceiverEventLogSize
) {
724 // We use this to do event timestamp sorting and truncating for events of
726 std::vector
<RtcpReceiverEventLogMessage
> sorted_log_messages
;
728 // Account for the RTCP header for an application-defined packet.
729 remaining_space
-= kRtcpCastLogHeaderSize
;
731 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit
=
732 rtcp_events
.rbegin();
734 while (rit
!= rtcp_events
.rend() &&
736 kRtcpReceiverFrameLogSize
+ kRtcpReceiverEventLogSize
) {
737 const RtpTimestamp rtp_timestamp
= rit
->first
;
738 RtcpReceiverFrameLogMessage
frame_log(rtp_timestamp
);
739 remaining_space
-= kRtcpReceiverFrameLogSize
;
742 // Get all events of a single frame.
743 sorted_log_messages
.clear();
745 RtcpReceiverEventLogMessage event_log_message
;
746 event_log_message
.type
= rit
->second
.type
;
747 event_log_message
.event_timestamp
= rit
->second
.timestamp
;
748 event_log_message
.delay_delta
= rit
->second
.delay_delta
;
749 event_log_message
.packet_id
= rit
->second
.packet_id
;
750 sorted_log_messages
.push_back(event_log_message
);
752 } while (rit
!= rtcp_events
.rend() && rit
->first
== rtp_timestamp
);
754 std::sort(sorted_log_messages
.begin(),
755 sorted_log_messages
.end(),
756 &EventTimestampLessThan
);
758 // From |sorted_log_messages|, only take events that are no greater than
759 // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events
760 // older than that cannot be encoded over the wire.
761 std::vector
<RtcpReceiverEventLogMessage
>::reverse_iterator sorted_rit
=
762 sorted_log_messages
.rbegin();
763 base::TimeTicks first_event_timestamp
= sorted_rit
->event_timestamp
;
764 size_t events_in_frame
= 0;
765 while (sorted_rit
!= sorted_log_messages
.rend() &&
766 events_in_frame
< kRtcpMaxReceiverLogMessages
&&
767 remaining_space
>= kRtcpReceiverEventLogSize
) {
768 base::TimeDelta
delta(first_event_timestamp
-
769 sorted_rit
->event_timestamp
);
770 if (delta
.InMilliseconds() > kMaxWireFormatTimeDeltaMs
)
772 frame_log
.event_log_messages_
.push_front(*sorted_rit
);
774 ++*total_number_of_messages_to_send
;
775 remaining_space
-= kRtcpReceiverEventLogSize
;
779 receiver_log_message
->push_front(frame_log
);
782 rtcp_events_history_
.push_front(*receiver_log_message
);
784 // We don't try to match RTP timestamps of redundancy frame logs with those
785 // from the newest set (which would save the space of an extra RTP timestamp
786 // over the wire). Unless the redundancy frame logs are very recent, it's
787 // unlikely there will be a match anyway.
788 if (rtcp_events_history_
.size() > kFirstRedundancyOffset
) {
789 // Add first redundnacy messages, if enough space remaining
790 AddReceiverLog(rtcp_events_history_
[kFirstRedundancyOffset
],
791 receiver_log_message
,
794 total_number_of_messages_to_send
);
797 if (rtcp_events_history_
.size() > kSecondRedundancyOffset
) {
798 // Add second redundancy messages, if enough space remaining
799 AddReceiverLog(rtcp_events_history_
[kSecondRedundancyOffset
],
800 receiver_log_message
,
803 total_number_of_messages_to_send
);
806 if (rtcp_events_history_
.size() > kReceiveLogMessageHistorySize
) {
807 rtcp_events_history_
.pop_back();
810 DCHECK_LE(rtcp_events_history_
.size(), kReceiveLogMessageHistorySize
);
813 kRtcpCastLogHeaderSize
+ *number_of_frames
* kRtcpReceiverFrameLogSize
+
814 *total_number_of_messages_to_send
* kRtcpReceiverEventLogSize
;
815 DCHECK_GE(kMaxIpPacketSize
, start_size
+ *rtcp_log_size
)
816 << "Not enough buffer space.";
818 VLOG(3) << "number of frames: " << *number_of_frames
;
819 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send
;
820 VLOG(3) << "rtcp log size: " << *rtcp_log_size
;
821 return *number_of_frames
> 0;