1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cast/net/rtcp/rtcp_builder.h"
12 #include "base/logging.h"
13 #include "media/cast/net/cast_transport_defines.h"
14 #include "media/cast/net/rtcp/rtcp_defines.h"
15 #include "media/cast/net/rtcp/rtcp_utility.h"
21 // Max delta is 4095 milliseconds because we need to be able to encode it in
23 const int64 kMaxWireFormatTimeDeltaMs
= INT64_C(0xfff);
25 uint16
MergeEventTypeAndTimestampForWireFormat(
26 const CastLoggingEvent
& event
,
27 const base::TimeDelta
& time_delta
) {
28 int64 time_delta_ms
= time_delta
.InMilliseconds();
30 DCHECK_GE(time_delta_ms
, 0);
31 DCHECK_LE(time_delta_ms
, kMaxWireFormatTimeDeltaMs
);
33 uint16 time_delta_12_bits
=
34 static_cast<uint16
>(time_delta_ms
& kMaxWireFormatTimeDeltaMs
);
36 uint16 event_type_4_bits
= ConvertEventTypeToWireFormat(event
);
37 DCHECK(event_type_4_bits
);
38 DCHECK(~(event_type_4_bits
& 0xfff0));
39 return (event_type_4_bits
<< 12) | time_delta_12_bits
;
42 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage
& lhs
,
43 const RtcpReceiverEventLogMessage
& rhs
) {
44 return lhs
.event_timestamp
< rhs
.event_timestamp
;
47 // A class to build a string representing the NACK list in Cast message.
49 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame
50 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of
51 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
52 // completely missing will show as "26:65535".
53 class NackStringBuilder
{
60 contiguous_sequence_(false) {}
61 ~NackStringBuilder() {}
63 bool Empty() const { return frame_count_
== 0; }
65 void PushFrame(int frame_id
) {
66 DCHECK_GE(frame_id
, 0);
67 if (frame_count_
> 0) {
68 if (frame_id
== last_frame_id_
) {
71 if (contiguous_sequence_
) {
72 stream_
<< "-" << last_packet_id_
;
77 last_frame_id_
= frame_id
;
79 contiguous_sequence_
= false;
83 void PushPacket(int packet_id
) {
84 DCHECK_GE(last_frame_id_
, 0);
85 DCHECK_GE(packet_id
, 0);
86 if (packet_count_
== 0) {
87 stream_
<< ":" << packet_id
;
88 } else if (packet_id
== last_packet_id_
+ 1) {
89 contiguous_sequence_
= true;
91 if (contiguous_sequence_
) {
92 stream_
<< "-" << last_packet_id_
;
93 contiguous_sequence_
= false;
95 stream_
<< "," << packet_id
;
98 last_packet_id_
= packet_id
;
101 std::string
GetString() {
102 if (contiguous_sequence_
) {
103 stream_
<< "-" << last_packet_id_
;
104 contiguous_sequence_
= false;
106 return stream_
.str();
110 std::ostringstream stream_
;
115 bool contiguous_sequence_
;
119 RtcpBuilder::RtcpBuilder(uint32 sending_ssrc
)
122 ptr_of_length_(NULL
) {
125 RtcpBuilder::~RtcpBuilder() {}
127 void RtcpBuilder::PatchLengthField() {
128 if (ptr_of_length_
) {
129 // Back-patch the packet length. The client must have taken
130 // care of proper padding to 32-bit words.
131 int this_packet_length
= (writer_
.ptr() - ptr_of_length_
- 2);
132 DCHECK_EQ(0, this_packet_length
% 4)
133 << "Packets must be a multiple of 32 bits long";
134 *ptr_of_length_
= this_packet_length
>> 10;
135 *(ptr_of_length_
+ 1) = (this_packet_length
>> 2) & 0xFF;
136 ptr_of_length_
= NULL
;
140 // Set the 5-bit value in the 1st byte of the header
141 // and the payload type. Set aside room for the length field,
142 // and make provision for back-patching it.
143 void RtcpBuilder::AddRtcpHeader(RtcpPacketFields payload
, int format_or_count
) {
145 writer_
.WriteU8(0x80 | (format_or_count
& 0x1F));
146 writer_
.WriteU8(payload
);
147 ptr_of_length_
= writer_
.ptr();
149 // Initialize length to "clearly illegal".
150 writer_
.WriteU16(0xDEAD);
153 void RtcpBuilder::Start() {
154 packet_
= new base::RefCountedData
<Packet
>;
155 packet_
->data
.resize(kMaxIpPacketSize
);
156 writer_
= base::BigEndianWriter(
157 reinterpret_cast<char*>(&(packet_
->data
[0])), kMaxIpPacketSize
);
160 PacketRef
RtcpBuilder::Finish() {
162 packet_
->data
.resize(kMaxIpPacketSize
- writer_
.remaining());
163 writer_
= base::BigEndianWriter(NULL
, 0);
164 PacketRef ret
= packet_
;
169 PacketRef
RtcpBuilder::BuildRtcpFromReceiver(
170 const RtcpReportBlock
* report_block
,
171 const RtcpReceiverReferenceTimeReport
* rrtr
,
172 const RtcpCastMessage
* cast_message
,
173 const ReceiverRtcpEventSubscriber::RtcpEvents
* rtcp_events
,
174 base::TimeDelta target_delay
) {
182 AddCast(cast_message
, target_delay
);
184 AddReceiverLog(*rtcp_events
);
189 PacketRef
RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo
& sender_info
) {
195 void RtcpBuilder::AddRR(const RtcpReportBlock
* report_block
) {
196 AddRtcpHeader(kPacketTypeReceiverReport
, report_block
? 1 : 0);
197 writer_
.WriteU32(ssrc_
);
199 AddReportBlocks(*report_block
); // Adds 24 bytes.
203 void RtcpBuilder::AddReportBlocks(const RtcpReportBlock
& report_block
) {
204 writer_
.WriteU32(report_block
.media_ssrc
);
205 writer_
.WriteU8(report_block
.fraction_lost
);
206 writer_
.WriteU8(report_block
.cumulative_lost
>> 16);
207 writer_
.WriteU8(report_block
.cumulative_lost
>> 8);
208 writer_
.WriteU8(report_block
.cumulative_lost
);
210 // Extended highest seq_no, contain the highest sequence number received.
211 writer_
.WriteU32(report_block
.extended_high_sequence_number
);
212 writer_
.WriteU32(report_block
.jitter
);
214 // Last SR timestamp; our NTP time when we received the last report.
215 // This is the value that we read from the send report packet not when we
217 writer_
.WriteU32(report_block
.last_sr
);
219 // Delay since last received report, time since we received the report.
220 writer_
.WriteU32(report_block
.delay_since_last_sr
);
223 void RtcpBuilder::AddRrtr(const RtcpReceiverReferenceTimeReport
* rrtr
) {
224 AddRtcpHeader(kPacketTypeXr
, 0);
225 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
226 writer_
.WriteU8(4); // Add block type.
227 writer_
.WriteU8(0); // Add reserved.
228 writer_
.WriteU16(2); // Block length.
230 // Add the media (received RTP) SSRC.
231 writer_
.WriteU32(rrtr
->ntp_seconds
);
232 writer_
.WriteU32(rrtr
->ntp_fraction
);
235 void RtcpBuilder::AddCast(const RtcpCastMessage
* cast
,
236 base::TimeDelta target_delay
) {
237 // See RTC 4585 Section 6.4 for application specific feedback messages.
238 AddRtcpHeader(kPacketTypePayloadSpecific
, 15);
239 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
240 writer_
.WriteU32(cast
->media_ssrc
); // Remote SSRC.
241 writer_
.WriteU32(kCast
);
242 writer_
.WriteU8(static_cast<uint8
>(cast
->ack_frame_id
));
243 uint8
* cast_loss_field_pos
= reinterpret_cast<uint8
*>(writer_
.ptr());
244 writer_
.WriteU8(0); // Overwritten with number_of_loss_fields.
245 DCHECK_LE(target_delay
.InMilliseconds(),
246 std::numeric_limits
<uint16_t>::max());
247 writer_
.WriteU16(target_delay
.InMilliseconds());
249 size_t number_of_loss_fields
= 0;
250 size_t max_number_of_loss_fields
= std::min
<size_t>(
251 kRtcpMaxCastLossFields
, writer_
.remaining() / 4);
253 MissingFramesAndPacketsMap::const_iterator frame_it
=
254 cast
->missing_frames_and_packets
.begin();
256 NackStringBuilder nack_string_builder
;
257 for (; frame_it
!= cast
->missing_frames_and_packets
.end() &&
258 number_of_loss_fields
< max_number_of_loss_fields
;
260 nack_string_builder
.PushFrame(frame_it
->first
);
261 // Iterate through all frames with missing packets.
262 if (frame_it
->second
.empty()) {
263 // Special case all packets in a frame is missing.
264 writer_
.WriteU8(static_cast<uint8
>(frame_it
->first
));
265 writer_
.WriteU16(kRtcpCastAllPacketsLost
);
267 nack_string_builder
.PushPacket(kRtcpCastAllPacketsLost
);
268 ++number_of_loss_fields
;
270 PacketIdSet::const_iterator packet_it
= frame_it
->second
.begin();
271 while (packet_it
!= frame_it
->second
.end()) {
272 uint16 packet_id
= *packet_it
;
273 // Write frame and packet id to buffer before calculating bitmask.
274 writer_
.WriteU8(static_cast<uint8
>(frame_it
->first
));
275 writer_
.WriteU16(packet_id
);
276 nack_string_builder
.PushPacket(packet_id
);
280 while (packet_it
!= frame_it
->second
.end()) {
281 int shift
= static_cast<uint8
>(*packet_it
- packet_id
) - 1;
282 if (shift
>= 0 && shift
<= 7) {
283 nack_string_builder
.PushPacket(*packet_it
);
284 bitmask
|= (1 << shift
);
290 writer_
.WriteU8(bitmask
);
291 ++number_of_loss_fields
;
295 VLOG_IF(1, !nack_string_builder
.Empty())
296 << "SSRC: " << cast
->media_ssrc
297 << ", ACK: " << cast
->ack_frame_id
298 << ", NACK: " << nack_string_builder
.GetString();
299 DCHECK_LE(number_of_loss_fields
, kRtcpMaxCastLossFields
);
300 *cast_loss_field_pos
= static_cast<uint8
>(number_of_loss_fields
);
303 void RtcpBuilder::AddSR(const RtcpSenderInfo
& sender_info
) {
304 AddRtcpHeader(kPacketTypeSenderReport
, 0);
305 writer_
.WriteU32(ssrc_
);
306 writer_
.WriteU32(sender_info
.ntp_seconds
);
307 writer_
.WriteU32(sender_info
.ntp_fraction
);
308 writer_
.WriteU32(sender_info
.rtp_timestamp
);
309 writer_
.WriteU32(sender_info
.send_packet_count
);
310 writer_
.WriteU32(static_cast<uint32
>(sender_info
.send_octet_count
));
315 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
316 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
317 |V=2|P|reserved | PT=XR=207 | length |
318 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
321 | BT=5 | reserved | block length |
322 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
323 | SSRC1 (SSRC of first receiver) | sub-
324 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
326 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327 | delay since last RR (DLRR) |
328 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
330 void RtcpBuilder::AddDlrrRb(const RtcpDlrrReportBlock
& dlrr
) {
331 AddRtcpHeader(kPacketTypeXr
, 0);
332 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
333 writer_
.WriteU8(5); // Add block type.
334 writer_
.WriteU8(0); // Add reserved.
335 writer_
.WriteU16(3); // Block length.
336 writer_
.WriteU32(ssrc_
); // Add the media (received RTP) SSRC.
337 writer_
.WriteU32(dlrr
.last_rr
);
338 writer_
.WriteU32(dlrr
.delay_since_last_rr
);
341 void RtcpBuilder::AddReceiverLog(
342 const ReceiverRtcpEventSubscriber::RtcpEvents
& rtcp_events
) {
343 size_t total_number_of_messages_to_send
= 0;
344 RtcpReceiverLogMessage receiver_log_message
;
346 if (!GetRtcpReceiverLogMessage(rtcp_events
,
347 &receiver_log_message
,
348 &total_number_of_messages_to_send
)) {
352 AddRtcpHeader(kPacketTypeApplicationDefined
, kReceiverLogSubtype
);
353 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
354 writer_
.WriteU32(kCast
);
356 while (!receiver_log_message
.empty() &&
357 total_number_of_messages_to_send
> 0) {
358 RtcpReceiverFrameLogMessage
& frame_log_messages(
359 receiver_log_message
.front());
361 // Add our frame header.
362 writer_
.WriteU32(frame_log_messages
.rtp_timestamp_
);
363 size_t messages_in_frame
= frame_log_messages
.event_log_messages_
.size();
364 if (messages_in_frame
> total_number_of_messages_to_send
) {
365 // We are running out of space.
366 messages_in_frame
= total_number_of_messages_to_send
;
368 // Keep track of how many messages we have left to send.
369 total_number_of_messages_to_send
-= messages_in_frame
;
371 // On the wire format is number of messages - 1.
372 writer_
.WriteU8(static_cast<uint8
>(messages_in_frame
- 1));
374 base::TimeTicks event_timestamp_base
=
375 frame_log_messages
.event_log_messages_
.front().event_timestamp
;
376 uint32 base_timestamp_ms
=
377 (event_timestamp_base
- base::TimeTicks()).InMilliseconds();
378 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 16));
379 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 8));
380 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
));
382 while (!frame_log_messages
.event_log_messages_
.empty() &&
383 messages_in_frame
> 0) {
384 const RtcpReceiverEventLogMessage
& event_message
=
385 frame_log_messages
.event_log_messages_
.front();
386 uint16 event_type_and_timestamp_delta
=
387 MergeEventTypeAndTimestampForWireFormat(
389 event_message
.event_timestamp
- event_timestamp_base
);
390 switch (event_message
.type
) {
395 static_cast<uint16
>(event_message
.delay_delta
.InMilliseconds()));
396 writer_
.WriteU16(event_type_and_timestamp_delta
);
398 case PACKET_RECEIVED
:
399 writer_
.WriteU16(event_message
.packet_id
);
400 writer_
.WriteU16(event_type_and_timestamp_delta
);
406 frame_log_messages
.event_log_messages_
.pop_front();
408 if (frame_log_messages
.event_log_messages_
.empty()) {
409 // We sent all messages on this frame; pop the frame header.
410 receiver_log_message
.pop_front();
413 DCHECK_EQ(total_number_of_messages_to_send
, 0u);
416 bool RtcpBuilder::GetRtcpReceiverLogMessage(
417 const ReceiverRtcpEventSubscriber::RtcpEvents
& rtcp_events
,
418 RtcpReceiverLogMessage
* receiver_log_message
,
419 size_t* total_number_of_messages_to_send
) {
420 size_t number_of_frames
= 0;
421 size_t remaining_space
= writer_
.remaining();
422 if (remaining_space
< kRtcpCastLogHeaderSize
+ kRtcpReceiverFrameLogSize
+
423 kRtcpReceiverEventLogSize
) {
427 // We use this to do event timestamp sorting and truncating for events of
429 std::vector
<RtcpReceiverEventLogMessage
> sorted_log_messages
;
431 // Account for the RTCP header for an application-defined packet.
432 remaining_space
-= kRtcpCastLogHeaderSize
;
434 ReceiverRtcpEventSubscriber::RtcpEvents::const_reverse_iterator rit
=
435 rtcp_events
.rbegin();
437 while (rit
!= rtcp_events
.rend() &&
439 kRtcpReceiverFrameLogSize
+ kRtcpReceiverEventLogSize
) {
440 const RtpTimestamp rtp_timestamp
= rit
->first
;
441 RtcpReceiverFrameLogMessage
frame_log(rtp_timestamp
);
442 remaining_space
-= kRtcpReceiverFrameLogSize
;
445 // Get all events of a single frame.
446 sorted_log_messages
.clear();
448 RtcpReceiverEventLogMessage event_log_message
;
449 event_log_message
.type
= rit
->second
.type
;
450 event_log_message
.event_timestamp
= rit
->second
.timestamp
;
451 event_log_message
.delay_delta
= rit
->second
.delay_delta
;
452 event_log_message
.packet_id
= rit
->second
.packet_id
;
453 sorted_log_messages
.push_back(event_log_message
);
455 } while (rit
!= rtcp_events
.rend() && rit
->first
== rtp_timestamp
);
457 std::sort(sorted_log_messages
.begin(),
458 sorted_log_messages
.end(),
459 &EventTimestampLessThan
);
461 // From |sorted_log_messages|, only take events that are no greater than
462 // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events
463 // older than that cannot be encoded over the wire.
464 std::vector
<RtcpReceiverEventLogMessage
>::reverse_iterator sorted_rit
=
465 sorted_log_messages
.rbegin();
466 base::TimeTicks first_event_timestamp
= sorted_rit
->event_timestamp
;
467 size_t events_in_frame
= 0;
468 while (sorted_rit
!= sorted_log_messages
.rend() &&
469 events_in_frame
< kRtcpMaxReceiverLogMessages
&&
470 remaining_space
>= kRtcpReceiverEventLogSize
) {
471 base::TimeDelta
delta(first_event_timestamp
-
472 sorted_rit
->event_timestamp
);
473 if (delta
.InMilliseconds() > kMaxWireFormatTimeDeltaMs
)
475 frame_log
.event_log_messages_
.push_front(*sorted_rit
);
477 ++*total_number_of_messages_to_send
;
478 remaining_space
-= kRtcpReceiverEventLogSize
;
482 receiver_log_message
->push_front(frame_log
);
485 VLOG(3) << "number of frames: " << number_of_frames
;
486 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send
;
487 return number_of_frames
> 0;