Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / media / cast / net / rtcp / rtcp_builder.cc
blob6f25a99105a36c0a768cac6c8f5ee5c75bce5f05
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"
7 #include <stdint.h>
9 #include <algorithm>
10 #include <vector>
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"
17 namespace media {
18 namespace cast {
19 namespace {
21 // Max delta is 4095 milliseconds because we need to be able to encode it in
22 // 12 bits.
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 {
54 public:
55 NackStringBuilder()
56 : frame_count_(0),
57 packet_count_(0),
58 last_frame_id_(-1),
59 last_packet_id_(-1),
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_) {
69 return;
71 if (contiguous_sequence_) {
72 stream_ << "-" << last_packet_id_;
74 stream_ << ", ";
76 stream_ << frame_id;
77 last_frame_id_ = frame_id;
78 packet_count_ = 0;
79 contiguous_sequence_ = false;
80 ++frame_count_;
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;
90 } else {
91 if (contiguous_sequence_) {
92 stream_ << "-" << last_packet_id_;
93 contiguous_sequence_ = false;
95 stream_ << "," << packet_id;
97 ++packet_count_;
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();
109 private:
110 std::ostringstream stream_;
111 int frame_count_;
112 int packet_count_;
113 int last_frame_id_;
114 int last_packet_id_;
115 bool contiguous_sequence_;
117 } // namespace
119 RtcpBuilder::RtcpBuilder(uint32 sending_ssrc)
120 : writer_(NULL, 0),
121 ssrc_(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) {
144 PatchLengthField();
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() {
161 PatchLengthField();
162 packet_->data.resize(kMaxIpPacketSize - writer_.remaining());
163 writer_ = base::BigEndianWriter(NULL, 0);
164 PacketRef ret = packet_;
165 packet_ = NULL;
166 return ret;
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) {
175 Start();
177 if (report_block)
178 AddRR(report_block);
179 if (rrtr)
180 AddRrtr(rrtr);
181 if (cast_message)
182 AddCast(cast_message, target_delay);
183 if (rtcp_events)
184 AddReceiverLog(*rtcp_events);
186 return Finish();
189 PacketRef RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo& sender_info) {
190 Start();
191 AddSR(sender_info);
192 return Finish();
195 void RtcpBuilder::AddRR(const RtcpReportBlock* report_block) {
196 AddRtcpHeader(kPacketTypeReceiverReport, report_block ? 1 : 0);
197 writer_.WriteU32(ssrc_);
198 if (report_block) {
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
216 // received it.
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;
259 ++frame_it) {
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);
266 writer_.WriteU8(0);
267 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost);
268 ++number_of_loss_fields;
269 } else {
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);
278 uint8 bitmask = 0;
279 ++packet_it;
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);
285 ++packet_it;
286 } else {
287 break;
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));
314 0 1 2 3
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319 | SSRC |
320 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
321 | BT=5 | reserved | block length |
322 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
323 | SSRC1 (SSRC of first receiver) | sub-
324 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
325 | last RR (LRR) | 1
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)) {
349 return;
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(
388 event_message.type,
389 event_message.event_timestamp - event_timestamp_base);
390 switch (event_message.type) {
391 case FRAME_ACK_SENT:
392 case FRAME_PLAYOUT:
393 case FRAME_DECODED:
394 writer_.WriteU16(
395 static_cast<uint16>(event_message.delay_delta.InMilliseconds()));
396 writer_.WriteU16(event_type_and_timestamp_delta);
397 break;
398 case PACKET_RECEIVED:
399 writer_.WriteU16(event_message.packet_id);
400 writer_.WriteU16(event_type_and_timestamp_delta);
401 break;
402 default:
403 NOTREACHED();
405 messages_in_frame--;
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) {
424 return false;
427 // We use this to do event timestamp sorting and truncating for events of
428 // a single frame.
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() &&
438 remaining_space >=
439 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
440 const RtpTimestamp rtp_timestamp = rit->first;
441 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
442 remaining_space -= kRtcpReceiverFrameLogSize;
443 ++number_of_frames;
445 // Get all events of a single frame.
446 sorted_log_messages.clear();
447 do {
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);
454 ++rit;
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)
474 break;
475 frame_log.event_log_messages_.push_front(*sorted_rit);
476 ++events_in_frame;
477 ++*total_number_of_messages_to_send;
478 remaining_space -= kRtcpReceiverEventLogSize;
479 ++sorted_rit;
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;
490 } // namespace cast
491 } // namespace media