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/rtcp/rtcp_utility.h"
19 // Max delta is 4095 milliseconds because we need to be able to encode it in
21 const int64 kMaxWireFormatTimeDeltaMs
= INT64_C(0xfff);
23 uint16
MergeEventTypeAndTimestampForWireFormat(
24 const CastLoggingEvent
& event
,
25 const base::TimeDelta
& time_delta
) {
26 int64 time_delta_ms
= time_delta
.InMilliseconds();
28 DCHECK_GE(time_delta_ms
, 0);
29 DCHECK_LE(time_delta_ms
, kMaxWireFormatTimeDeltaMs
);
31 uint16 time_delta_12_bits
=
32 static_cast<uint16
>(time_delta_ms
& kMaxWireFormatTimeDeltaMs
);
34 uint16 event_type_4_bits
= ConvertEventTypeToWireFormat(event
);
35 DCHECK(event_type_4_bits
);
36 DCHECK(~(event_type_4_bits
& 0xfff0));
37 return (event_type_4_bits
<< 12) | time_delta_12_bits
;
40 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage
& lhs
,
41 const RtcpReceiverEventLogMessage
& rhs
) {
42 return lhs
.event_timestamp
< rhs
.event_timestamp
;
45 // A class to build a string representing the NACK list in Cast message.
47 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame
48 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of
49 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
50 // completely missing will show as "26:65535".
51 class NackStringBuilder
{
58 contiguous_sequence_(false) {}
59 ~NackStringBuilder() {}
61 bool Empty() const { return frame_count_
== 0; }
63 void PushFrame(int frame_id
) {
64 DCHECK_GE(frame_id
, 0);
65 if (frame_count_
> 0) {
66 if (frame_id
== last_frame_id_
) {
69 if (contiguous_sequence_
) {
70 stream_
<< "-" << last_packet_id_
;
75 last_frame_id_
= frame_id
;
77 contiguous_sequence_
= false;
81 void PushPacket(int packet_id
) {
82 DCHECK_GE(last_frame_id_
, 0);
83 DCHECK_GE(packet_id
, 0);
84 if (packet_count_
== 0) {
85 stream_
<< ":" << packet_id
;
86 } else if (packet_id
== last_packet_id_
+ 1) {
87 contiguous_sequence_
= true;
89 if (contiguous_sequence_
) {
90 stream_
<< "-" << last_packet_id_
;
91 contiguous_sequence_
= false;
93 stream_
<< "," << packet_id
;
96 last_packet_id_
= packet_id
;
99 std::string
GetString() {
100 if (contiguous_sequence_
) {
101 stream_
<< "-" << last_packet_id_
;
102 contiguous_sequence_
= false;
104 return stream_
.str();
108 std::ostringstream stream_
;
113 bool contiguous_sequence_
;
117 RtcpBuilder::RtcpBuilder(uint32 sending_ssrc
)
120 ptr_of_length_(NULL
) {
123 RtcpBuilder::~RtcpBuilder() {}
125 void RtcpBuilder::PatchLengthField() {
126 if (ptr_of_length_
) {
127 // Back-patch the packet length. The client must have taken
128 // care of proper padding to 32-bit words.
129 int this_packet_length
= (writer_
.ptr() - ptr_of_length_
- 2);
130 DCHECK_EQ(0, this_packet_length
% 4)
131 << "Packets must be a multiple of 32 bits long";
132 *ptr_of_length_
= this_packet_length
>> 10;
133 *(ptr_of_length_
+ 1) = (this_packet_length
>> 2) & 0xFF;
134 ptr_of_length_
= NULL
;
138 // Set the 5-bit value in the 1st byte of the header
139 // and the payload type. Set aside room for the length field,
140 // and make provision for back-patching it.
141 void RtcpBuilder::AddRtcpHeader(RtcpPacketFields payload
, int format_or_count
) {
143 writer_
.WriteU8(0x80 | (format_or_count
& 0x1F));
144 writer_
.WriteU8(payload
);
145 ptr_of_length_
= writer_
.ptr();
147 // Initialize length to "clearly illegal".
148 writer_
.WriteU16(0xDEAD);
151 void RtcpBuilder::Start() {
152 packet_
= new base::RefCountedData
<Packet
>;
153 packet_
->data
.resize(kMaxIpPacketSize
);
154 writer_
= base::BigEndianWriter(
155 reinterpret_cast<char*>(&(packet_
->data
[0])), kMaxIpPacketSize
);
158 PacketRef
RtcpBuilder::Finish() {
160 packet_
->data
.resize(kMaxIpPacketSize
- writer_
.remaining());
161 writer_
= base::BigEndianWriter(NULL
, 0);
162 PacketRef ret
= packet_
;
167 PacketRef
RtcpBuilder::BuildRtcpFromReceiver(
168 const RtcpReportBlock
* report_block
,
169 const RtcpReceiverReferenceTimeReport
* rrtr
,
170 const RtcpCastMessage
* cast_message
,
171 const ReceiverRtcpEventSubscriber::RtcpEvents
* rtcp_events
,
172 base::TimeDelta target_delay
) {
180 AddCast(cast_message
, target_delay
);
182 AddReceiverLog(*rtcp_events
);
187 PacketRef
RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo
& sender_info
) {
193 void RtcpBuilder::AddRR(const RtcpReportBlock
* report_block
) {
194 AddRtcpHeader(kPacketTypeReceiverReport
, report_block
? 1 : 0);
195 writer_
.WriteU32(ssrc_
);
197 AddReportBlocks(*report_block
); // Adds 24 bytes.
201 void RtcpBuilder::AddReportBlocks(const RtcpReportBlock
& report_block
) {
202 writer_
.WriteU32(report_block
.media_ssrc
);
203 writer_
.WriteU8(report_block
.fraction_lost
);
204 writer_
.WriteU8(report_block
.cumulative_lost
>> 16);
205 writer_
.WriteU8(report_block
.cumulative_lost
>> 8);
206 writer_
.WriteU8(report_block
.cumulative_lost
);
208 // Extended highest seq_no, contain the highest sequence number received.
209 writer_
.WriteU32(report_block
.extended_high_sequence_number
);
210 writer_
.WriteU32(report_block
.jitter
);
212 // Last SR timestamp; our NTP time when we received the last report.
213 // This is the value that we read from the send report packet not when we
215 writer_
.WriteU32(report_block
.last_sr
);
217 // Delay since last received report, time since we received the report.
218 writer_
.WriteU32(report_block
.delay_since_last_sr
);
221 void RtcpBuilder::AddRrtr(const RtcpReceiverReferenceTimeReport
* rrtr
) {
222 AddRtcpHeader(kPacketTypeXr
, 0);
223 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
224 writer_
.WriteU8(4); // Add block type.
225 writer_
.WriteU8(0); // Add reserved.
226 writer_
.WriteU16(2); // Block length.
228 // Add the media (received RTP) SSRC.
229 writer_
.WriteU32(rrtr
->ntp_seconds
);
230 writer_
.WriteU32(rrtr
->ntp_fraction
);
233 void RtcpBuilder::AddCast(const RtcpCastMessage
* cast
,
234 base::TimeDelta target_delay
) {
235 // See RTC 4585 Section 6.4 for application specific feedback messages.
236 AddRtcpHeader(kPacketTypePayloadSpecific
, 15);
237 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
238 writer_
.WriteU32(cast
->media_ssrc
); // Remote SSRC.
239 writer_
.WriteU32(kCast
);
240 writer_
.WriteU8(static_cast<uint8
>(cast
->ack_frame_id
));
241 uint8
* cast_loss_field_pos
= reinterpret_cast<uint8
*>(writer_
.ptr());
242 writer_
.WriteU8(0); // Overwritten with number_of_loss_fields.
243 DCHECK_LE(target_delay
.InMilliseconds(),
244 std::numeric_limits
<uint16_t>::max());
245 writer_
.WriteU16(target_delay
.InMilliseconds());
247 size_t number_of_loss_fields
= 0;
248 size_t max_number_of_loss_fields
= std::min
<size_t>(
249 kRtcpMaxCastLossFields
, writer_
.remaining() / 4);
251 MissingFramesAndPacketsMap::const_iterator frame_it
=
252 cast
->missing_frames_and_packets
.begin();
254 NackStringBuilder nack_string_builder
;
255 for (; frame_it
!= cast
->missing_frames_and_packets
.end() &&
256 number_of_loss_fields
< max_number_of_loss_fields
;
258 nack_string_builder
.PushFrame(frame_it
->first
);
259 // Iterate through all frames with missing packets.
260 if (frame_it
->second
.empty()) {
261 // Special case all packets in a frame is missing.
262 writer_
.WriteU8(static_cast<uint8
>(frame_it
->first
));
263 writer_
.WriteU16(kRtcpCastAllPacketsLost
);
265 nack_string_builder
.PushPacket(kRtcpCastAllPacketsLost
);
266 ++number_of_loss_fields
;
268 PacketIdSet::const_iterator packet_it
= frame_it
->second
.begin();
269 while (packet_it
!= frame_it
->second
.end()) {
270 uint16 packet_id
= *packet_it
;
271 // Write frame and packet id to buffer before calculating bitmask.
272 writer_
.WriteU8(static_cast<uint8
>(frame_it
->first
));
273 writer_
.WriteU16(packet_id
);
274 nack_string_builder
.PushPacket(packet_id
);
278 while (packet_it
!= frame_it
->second
.end()) {
279 int shift
= static_cast<uint8
>(*packet_it
- packet_id
) - 1;
280 if (shift
>= 0 && shift
<= 7) {
281 nack_string_builder
.PushPacket(*packet_it
);
282 bitmask
|= (1 << shift
);
288 writer_
.WriteU8(bitmask
);
289 ++number_of_loss_fields
;
293 VLOG_IF(1, !nack_string_builder
.Empty())
294 << "SSRC: " << cast
->media_ssrc
295 << ", ACK: " << cast
->ack_frame_id
296 << ", NACK: " << nack_string_builder
.GetString();
297 DCHECK_LE(number_of_loss_fields
, kRtcpMaxCastLossFields
);
298 *cast_loss_field_pos
= static_cast<uint8
>(number_of_loss_fields
);
301 void RtcpBuilder::AddSR(const RtcpSenderInfo
& sender_info
) {
302 AddRtcpHeader(kPacketTypeSenderReport
, 0);
303 writer_
.WriteU32(ssrc_
);
304 writer_
.WriteU32(sender_info
.ntp_seconds
);
305 writer_
.WriteU32(sender_info
.ntp_fraction
);
306 writer_
.WriteU32(sender_info
.rtp_timestamp
);
307 writer_
.WriteU32(sender_info
.send_packet_count
);
308 writer_
.WriteU32(static_cast<uint32
>(sender_info
.send_octet_count
));
313 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
314 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
315 |V=2|P|reserved | PT=XR=207 | length |
316 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
318 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319 | BT=5 | reserved | block length |
320 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
321 | SSRC1 (SSRC of first receiver) | sub-
322 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
324 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325 | delay since last RR (DLRR) |
326 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
328 void RtcpBuilder::AddDlrrRb(const RtcpDlrrReportBlock
& dlrr
) {
329 AddRtcpHeader(kPacketTypeXr
, 0);
330 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
331 writer_
.WriteU8(5); // Add block type.
332 writer_
.WriteU8(0); // Add reserved.
333 writer_
.WriteU16(3); // Block length.
334 writer_
.WriteU32(ssrc_
); // Add the media (received RTP) SSRC.
335 writer_
.WriteU32(dlrr
.last_rr
);
336 writer_
.WriteU32(dlrr
.delay_since_last_rr
);
339 void RtcpBuilder::AddReceiverLog(
340 const ReceiverRtcpEventSubscriber::RtcpEvents
& rtcp_events
) {
341 size_t total_number_of_messages_to_send
= 0;
342 RtcpReceiverLogMessage receiver_log_message
;
344 if (!GetRtcpReceiverLogMessage(rtcp_events
,
345 &receiver_log_message
,
346 &total_number_of_messages_to_send
)) {
350 AddRtcpHeader(kPacketTypeApplicationDefined
, kReceiverLogSubtype
);
351 writer_
.WriteU32(ssrc_
); // Add our own SSRC.
352 writer_
.WriteU32(kCast
);
354 while (!receiver_log_message
.empty() &&
355 total_number_of_messages_to_send
> 0) {
356 RtcpReceiverFrameLogMessage
& frame_log_messages(
357 receiver_log_message
.front());
359 // Add our frame header.
360 writer_
.WriteU32(frame_log_messages
.rtp_timestamp_
);
361 size_t messages_in_frame
= frame_log_messages
.event_log_messages_
.size();
362 if (messages_in_frame
> total_number_of_messages_to_send
) {
363 // We are running out of space.
364 messages_in_frame
= total_number_of_messages_to_send
;
366 // Keep track of how many messages we have left to send.
367 total_number_of_messages_to_send
-= messages_in_frame
;
369 // On the wire format is number of messages - 1.
370 writer_
.WriteU8(static_cast<uint8
>(messages_in_frame
- 1));
372 base::TimeTicks event_timestamp_base
=
373 frame_log_messages
.event_log_messages_
.front().event_timestamp
;
374 uint32 base_timestamp_ms
=
375 (event_timestamp_base
- base::TimeTicks()).InMilliseconds();
376 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 16));
377 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
>> 8));
378 writer_
.WriteU8(static_cast<uint8
>(base_timestamp_ms
));
380 while (!frame_log_messages
.event_log_messages_
.empty() &&
381 messages_in_frame
> 0) {
382 const RtcpReceiverEventLogMessage
& event_message
=
383 frame_log_messages
.event_log_messages_
.front();
384 uint16 event_type_and_timestamp_delta
=
385 MergeEventTypeAndTimestampForWireFormat(
387 event_message
.event_timestamp
- event_timestamp_base
);
388 switch (event_message
.type
) {
393 static_cast<uint16
>(event_message
.delay_delta
.InMilliseconds()));
394 writer_
.WriteU16(event_type_and_timestamp_delta
);
396 case PACKET_RECEIVED
:
397 writer_
.WriteU16(event_message
.packet_id
);
398 writer_
.WriteU16(event_type_and_timestamp_delta
);
404 frame_log_messages
.event_log_messages_
.pop_front();
406 if (frame_log_messages
.event_log_messages_
.empty()) {
407 // We sent all messages on this frame; pop the frame header.
408 receiver_log_message
.pop_front();
411 DCHECK_EQ(total_number_of_messages_to_send
, 0u);
414 bool RtcpBuilder::GetRtcpReceiverLogMessage(
415 const ReceiverRtcpEventSubscriber::RtcpEvents
& rtcp_events
,
416 RtcpReceiverLogMessage
* receiver_log_message
,
417 size_t* total_number_of_messages_to_send
) {
418 size_t number_of_frames
= 0;
419 size_t remaining_space
= writer_
.remaining();
420 if (remaining_space
< kRtcpCastLogHeaderSize
+ kRtcpReceiverFrameLogSize
+
421 kRtcpReceiverEventLogSize
) {
425 // We use this to do event timestamp sorting and truncating for events of
427 std::vector
<RtcpReceiverEventLogMessage
> sorted_log_messages
;
429 // Account for the RTCP header for an application-defined packet.
430 remaining_space
-= kRtcpCastLogHeaderSize
;
432 ReceiverRtcpEventSubscriber::RtcpEvents::const_reverse_iterator rit
=
433 rtcp_events
.rbegin();
435 while (rit
!= rtcp_events
.rend() &&
437 kRtcpReceiverFrameLogSize
+ kRtcpReceiverEventLogSize
) {
438 const RtpTimestamp rtp_timestamp
= rit
->first
;
439 RtcpReceiverFrameLogMessage
frame_log(rtp_timestamp
);
440 remaining_space
-= kRtcpReceiverFrameLogSize
;
443 // Get all events of a single frame.
444 sorted_log_messages
.clear();
446 RtcpReceiverEventLogMessage event_log_message
;
447 event_log_message
.type
= rit
->second
.type
;
448 event_log_message
.event_timestamp
= rit
->second
.timestamp
;
449 event_log_message
.delay_delta
= rit
->second
.delay_delta
;
450 event_log_message
.packet_id
= rit
->second
.packet_id
;
451 sorted_log_messages
.push_back(event_log_message
);
453 } while (rit
!= rtcp_events
.rend() && rit
->first
== rtp_timestamp
);
455 std::sort(sorted_log_messages
.begin(),
456 sorted_log_messages
.end(),
457 &EventTimestampLessThan
);
459 // From |sorted_log_messages|, only take events that are no greater than
460 // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events
461 // older than that cannot be encoded over the wire.
462 std::vector
<RtcpReceiverEventLogMessage
>::reverse_iterator sorted_rit
=
463 sorted_log_messages
.rbegin();
464 base::TimeTicks first_event_timestamp
= sorted_rit
->event_timestamp
;
465 size_t events_in_frame
= 0;
466 while (sorted_rit
!= sorted_log_messages
.rend() &&
467 events_in_frame
< kRtcpMaxReceiverLogMessages
&&
468 remaining_space
>= kRtcpReceiverEventLogSize
) {
469 base::TimeDelta
delta(first_event_timestamp
-
470 sorted_rit
->event_timestamp
);
471 if (delta
.InMilliseconds() > kMaxWireFormatTimeDeltaMs
)
473 frame_log
.event_log_messages_
.push_front(*sorted_rit
);
475 ++*total_number_of_messages_to_send
;
476 remaining_space
-= kRtcpReceiverEventLogSize
;
480 receiver_log_message
->push_front(frame_log
);
483 VLOG(3) << "number of frames: " << number_of_frames
;
484 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send
;
485 return number_of_frames
> 0;