Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / cast / rtcp / rtcp_sender.cc
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.
4
5 #include "media/cast/rtcp/rtcp_sender.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "media/cast/cast_environment.h"
12 #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
13 #include "media/cast/rtcp/rtcp_defines.h"
14 #include "media/cast/rtcp/rtcp_utility.h"
15 #include "media/cast/transport/cast_transport_defines.h"
16 #include "media/cast/transport/pacing/paced_sender.h"
17 #include "net/base/big_endian.h"
18
19 namespace {
20
21 using media::cast::kRtcpCastLogHeaderSize;
22 using media::cast::kRtcpSenderFrameLogSize;
23 using media::cast::kRtcpReceiverFrameLogSize;
24 using media::cast::kRtcpReceiverEventLogSize;
25
26 // Converts a log event type to an integer value.
27 int ConvertEventTypeToWireFormat(const media::cast::CastLoggingEvent& event) {
28   switch (event) {
29     case media::cast::kAudioAckSent:
30       return 1;
31     case media::cast::kAudioPlayoutDelay:
32       return 2;
33     case media::cast::kAudioFrameDecoded:
34       return 3;
35     case media::cast::kAudioPacketReceived:
36       return 4;
37     case media::cast::kVideoAckSent:
38       return 5;
39     case media::cast::kVideoFrameDecoded:
40       return 6;
41     case media::cast::kVideoRenderDelay:
42       return 7;
43     case media::cast::kVideoPacketReceived:
44       return 8;
45     case media::cast::kDuplicateAudioPacketReceived:
46       return 9;
47     case media::cast::kDuplicateVideoPacketReceived:
48       return 10;
49     default:
50       return 0;  // Not an interesting event.
51   }
52 }
53
54 uint16 MergeEventTypeAndTimestampForWireFormat(
55     const media::cast::CastLoggingEvent& event,
56     const base::TimeDelta& time_delta) {
57   int64 time_delta_ms = time_delta.InMilliseconds();
58   // Max delta is 4096 milliseconds.
59   DCHECK_GE(GG_INT64_C(0xfff), time_delta_ms);
60
61   uint16 event_type_and_timestamp_delta =
62       static_cast<uint16>(time_delta_ms & 0xfff);
63
64   uint16 event_type = ConvertEventTypeToWireFormat(event);
65   DCHECK(event_type);
66   DCHECK(!(event_type & 0xfff0));
67   return (event_type << 12) + event_type_and_timestamp_delta;
68 }
69
70 bool ScanRtcpReceiverLogMessage(
71     const media::cast::RtcpReceiverLogMessage& receiver_log_message,
72     size_t start_size, size_t* number_of_frames,
73     size_t* total_number_of_messages_to_send, size_t* rtcp_log_size) {
74   if (receiver_log_message.empty()) return false;
75
76   size_t remaining_space = media::cast::kMaxIpPacketSize - start_size;
77
78   // We must have space for at least one message
79   DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize +
80                                  kRtcpReceiverFrameLogSize +
81                                  kRtcpReceiverEventLogSize)
82       << "Not enough buffer space";
83
84   if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
85                             kRtcpReceiverEventLogSize) {
86     return false;
87   }
88   // Account for the RTCP header for an application-defined packet.
89   remaining_space -= kRtcpCastLogHeaderSize;
90
91   media::cast::RtcpReceiverLogMessage::const_iterator frame_it =
92       receiver_log_message.begin();
93   for (; frame_it != receiver_log_message.end(); ++frame_it) {
94     (*number_of_frames)++;
95
96     remaining_space -= kRtcpReceiverFrameLogSize;
97
98     size_t messages_in_frame = frame_it->event_log_messages_.size();
99     size_t remaining_space_in_messages =
100         remaining_space / kRtcpReceiverEventLogSize;
101     size_t messages_to_send =
102         std::min(messages_in_frame, remaining_space_in_messages);
103     if (messages_to_send > media::cast::kRtcpMaxReceiverLogMessages) {
104       // We can't send more than 256 messages.
105       remaining_space -=
106           media::cast::kRtcpMaxReceiverLogMessages * kRtcpReceiverEventLogSize;
107       *total_number_of_messages_to_send +=
108           media::cast::kRtcpMaxReceiverLogMessages;
109       break;
110     }
111     remaining_space -= messages_to_send * kRtcpReceiverEventLogSize;
112     *total_number_of_messages_to_send += messages_to_send;
113
114     if (remaining_space <
115         kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
116       // Make sure that we have room for at least one more message.
117       break;
118     }
119   }
120   *rtcp_log_size =
121       kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize +
122       *total_number_of_messages_to_send * kRtcpReceiverEventLogSize;
123   DCHECK_GE(media::cast::kMaxIpPacketSize, start_size + *rtcp_log_size)
124       << "Not enough buffer space";
125
126   VLOG(1) << "number of frames " << *number_of_frames;
127   VLOG(1) << "total messages to send " << *total_number_of_messages_to_send;
128   VLOG(1) << "rtcp log size " << *rtcp_log_size;
129   return true;
130 }
131 }  // namespace
132
133 namespace media {
134 namespace cast {
135
136 // TODO(mikhal): This is only used by the receiver. Consider renaming.
137 RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
138                        transport::PacedPacketSender* outgoing_transport,
139                        uint32 sending_ssrc, const std::string& c_name)
140     : ssrc_(sending_ssrc),
141       c_name_(c_name),
142       transport_(outgoing_transport),
143       cast_environment_(cast_environment) {
144   DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config";
145 }
146
147 RtcpSender::~RtcpSender() {}
148
149 // static
150 bool RtcpSender::IsReceiverEvent(const media::cast::CastLoggingEvent& event) {
151   return ConvertEventTypeToWireFormat(event) != 0;
152 }
153
154 void RtcpSender::SendRtcpFromRtpReceiver(
155     uint32 packet_type_flags,
156     const transport::RtcpReportBlock* report_block,
157     const RtcpReceiverReferenceTimeReport* rrtr,
158     const RtcpCastMessage* cast_message,
159     ReceiverRtcpEventSubscriber* event_subscriber) {
160   if (packet_type_flags & kRtcpSr || packet_type_flags & kRtcpDlrr ||
161       packet_type_flags & kRtcpSenderLog) {
162     NOTREACHED() << "Invalid argument";
163   }
164   if (packet_type_flags & kRtcpPli || packet_type_flags & kRtcpRpsi ||
165       packet_type_flags & kRtcpRemb || packet_type_flags & kRtcpNack) {
166     // Implement these for webrtc interop.
167     NOTIMPLEMENTED();
168   }
169   Packet packet;
170   packet.reserve(kMaxIpPacketSize);
171
172   if (packet_type_flags & kRtcpRr) {
173     BuildRR(report_block, &packet);
174     if (!c_name_.empty()) {
175       BuildSdec(&packet);
176     }
177   }
178   if (packet_type_flags & kRtcpBye) {
179     BuildBye(&packet);
180   }
181   if (packet_type_flags & kRtcpRrtr) {
182     DCHECK(rrtr) << "Invalid argument";
183     BuildRrtr(rrtr, &packet);
184   }
185   if (packet_type_flags & kRtcpCast) {
186     DCHECK(cast_message) << "Invalid argument";
187     BuildCast(cast_message, &packet);
188   }
189   if (packet_type_flags & kRtcpReceiverLog) {
190     DCHECK(event_subscriber) << "Invalid argument";
191     RtcpReceiverLogMessage receiver_log;
192     event_subscriber->GetReceiverLogMessageAndReset(&receiver_log);
193     BuildReceiverLog(&receiver_log, &packet);
194   }
195   if (packet.empty()) return;  // Sanity don't send empty packets.
196
197   transport_->SendRtcpPacket(packet);
198 }
199
200 void RtcpSender::BuildRR(const transport::RtcpReportBlock* report_block,
201                          Packet* packet) const {
202   size_t start_size = packet->size();
203   DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space";
204   if (start_size + 32 > kMaxIpPacketSize) return;
205
206   uint16 number_of_rows = (report_block) ? 7 : 1;
207   packet->resize(start_size + 8);
208
209   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
210   big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
211   big_endian_writer.WriteU8(transport::kPacketTypeReceiverReport);
212   big_endian_writer.WriteU16(number_of_rows);
213   big_endian_writer.WriteU32(ssrc_);
214
215   if (report_block) {
216     AddReportBlocks(*report_block, packet);  // Adds 24 bytes.
217   }
218 }
219
220 void RtcpSender::AddReportBlocks(const transport::RtcpReportBlock& report_block,
221                                  Packet* packet) const {
222   size_t start_size = packet->size();
223   DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
224   if (start_size + 24 > kMaxIpPacketSize) return;
225
226   packet->resize(start_size + 24);
227
228   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
229   big_endian_writer.WriteU32(report_block.media_ssrc);
230   big_endian_writer.WriteU8(report_block.fraction_lost);
231   big_endian_writer.WriteU8(report_block.cumulative_lost >> 16);
232   big_endian_writer.WriteU8(report_block.cumulative_lost >> 8);
233   big_endian_writer.WriteU8(report_block.cumulative_lost);
234
235   // Extended highest seq_no, contain the highest sequence number received.
236   big_endian_writer.WriteU32(report_block.extended_high_sequence_number);
237   big_endian_writer.WriteU32(report_block.jitter);
238
239   // Last SR timestamp; our NTP time when we received the last report.
240   // This is the value that we read from the send report packet not when we
241   // received it.
242   big_endian_writer.WriteU32(report_block.last_sr);
243
244   // Delay since last received report, time since we received the report.
245   big_endian_writer.WriteU32(report_block.delay_since_last_sr);
246 }
247
248 void RtcpSender::BuildSdec(Packet* packet) const {
249   size_t start_size = packet->size();
250   DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize)
251       << "Not enough buffer space";
252   if (start_size + 12 > kMaxIpPacketSize) return;
253
254   // SDES Source Description.
255   packet->resize(start_size + 10);
256
257   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
258   // We always need to add one SDES CNAME.
259   big_endian_writer.WriteU8(0x80 + 1);
260   big_endian_writer.WriteU8(transport::kPacketTypeSdes);
261
262   // Handle SDES length later on.
263   uint32 sdes_length_position = static_cast<uint32>(start_size) + 3;
264   big_endian_writer.WriteU16(0);
265   big_endian_writer.WriteU32(ssrc_);  // Add our own SSRC.
266   big_endian_writer.WriteU8(1);       // CNAME = 1
267   big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length()));
268
269   size_t sdes_length = 10 + c_name_.length();
270   packet->insert(packet->end(), c_name_.c_str(),
271                  c_name_.c_str() + c_name_.length());
272
273   size_t padding = 0;
274
275   // We must have a zero field even if we have an even multiple of 4 bytes.
276   if ((packet->size() % 4) == 0) {
277     padding++;
278     packet->push_back(0);
279   }
280   while ((packet->size() % 4) != 0) {
281     padding++;
282     packet->push_back(0);
283   }
284   sdes_length += padding;
285
286   // In 32-bit words minus one and we don't count the header.
287   uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1);
288   (*packet)[sdes_length_position] = buffer_length;
289 }
290
291 void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const {
292   size_t start_size = packet->size();
293   DCHECK_LT(start_size + 12, kMaxIpPacketSize) << "Not enough buffer space";
294   if (start_size + 12 > kMaxIpPacketSize) return;
295
296   packet->resize(start_size + 12);
297
298   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 12);
299   uint8 FMT = 1;  // Picture loss indicator.
300   big_endian_writer.WriteU8(0x80 + FMT);
301   big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
302   big_endian_writer.WriteU16(2);            // Used fixed length of 2.
303   big_endian_writer.WriteU32(ssrc_);        // Add our own SSRC.
304   big_endian_writer.WriteU32(remote_ssrc);  // Add the remote SSRC.
305 }
306
307 /*
308     0                   1                   2                   3
309     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
310    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311    |      PB       |0| Payload Type|    Native Rpsi bit string     |
312    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313    |   defined per codec          ...                | Padding (0) |
314    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
315 */
316 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const {
317   size_t start_size = packet->size();
318   DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
319   if (start_size + 24 > kMaxIpPacketSize) return;
320
321   packet->resize(start_size + 24);
322
323   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
324   uint8 FMT = 3;  // Reference Picture Selection Indication.
325   big_endian_writer.WriteU8(0x80 + FMT);
326   big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
327
328   // Calculate length.
329   uint32 bits_required = 7;
330   uint8 bytes_required = 1;
331   while ((rpsi->picture_id >> bits_required) > 0) {
332     bits_required += 7;
333     bytes_required++;
334   }
335   uint8 size = 3;
336   if (bytes_required > 6) {
337     size = 5;
338   } else if (bytes_required > 2) {
339     size = 4;
340   }
341   big_endian_writer.WriteU8(0);
342   big_endian_writer.WriteU8(size);
343   big_endian_writer.WriteU32(ssrc_);
344   big_endian_writer.WriteU32(rpsi->remote_ssrc);
345
346   uint8 padding_bytes = 4 - ((2 + bytes_required) % 4);
347   if (padding_bytes == 4) {
348     padding_bytes = 0;
349   }
350   // Add padding length in bits, padding can be 0, 8, 16 or 24.
351   big_endian_writer.WriteU8(padding_bytes * 8);
352   big_endian_writer.WriteU8(rpsi->payload_type);
353
354   // Add picture ID.
355   for (int i = bytes_required - 1; i > 0; i--) {
356     big_endian_writer.WriteU8(0x80 |
357                               static_cast<uint8>(rpsi->picture_id >> (i * 7)));
358   }
359   // Add last byte of picture ID.
360   big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f));
361
362   // Add padding.
363   for (int j = 0; j < padding_bytes; ++j) {
364     big_endian_writer.WriteU8(0);
365   }
366 }
367
368 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const {
369   size_t start_size = packet->size();
370   size_t remb_size = 20 + 4 * remb->remb_ssrcs.size();
371   DCHECK_LT(start_size + remb_size, kMaxIpPacketSize)
372       << "Not enough buffer space";
373   if (start_size + remb_size > kMaxIpPacketSize) return;
374
375   packet->resize(start_size + remb_size);
376
377   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size);
378
379   // Add application layer feedback.
380   uint8 FMT = 15;
381   big_endian_writer.WriteU8(0x80 + FMT);
382   big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
383   big_endian_writer.WriteU8(0);
384   big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4));
385   big_endian_writer.WriteU32(ssrc_);  // Add our own SSRC.
386   big_endian_writer.WriteU32(0);      // Remote SSRC must be 0.
387   big_endian_writer.WriteU32(kRemb);
388   big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size()));
389
390   // 6 bit exponent and a 18 bit mantissa.
391   uint8 bitrate_exponent;
392   uint32 bitrate_mantissa;
393   BitrateToRembExponentBitrate(remb->remb_bitrate, &bitrate_exponent,
394                                &bitrate_mantissa);
395
396   big_endian_writer.WriteU8(static_cast<uint8>(
397       (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03)));
398   big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8));
399   big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa));
400
401   std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin();
402   for (; it != remb->remb_ssrcs.end(); ++it) {
403     big_endian_writer.WriteU32(*it);
404   }
405   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
406   cast_environment_->Logging()->InsertGenericEvent(now, kRembBitrate,
407                                                    remb->remb_bitrate);
408 }
409
410 void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const {
411   size_t start_size = packet->size();
412   DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space";
413   if (start_size + 16 > kMaxIpPacketSize) return;
414
415   packet->resize(start_size + 16);
416
417   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16);
418
419   uint8 FMT = 1;
420   big_endian_writer.WriteU8(0x80 + FMT);
421   big_endian_writer.WriteU8(transport::kPacketTypeGenericRtpFeedback);
422   big_endian_writer.WriteU8(0);
423   size_t nack_size_pos = start_size + 3;
424   big_endian_writer.WriteU8(3);
425   big_endian_writer.WriteU32(ssrc_);              // Add our own SSRC.
426   big_endian_writer.WriteU32(nack->remote_ssrc);  // Add the remote SSRC.
427
428   // Build NACK bitmasks and write them to the Rtcp message.
429   // The nack list should be sorted and not contain duplicates.
430   size_t number_of_nack_fields = 0;
431   size_t max_number_of_nack_fields = std::min<size_t>(
432       kRtcpMaxNackFields, (kMaxIpPacketSize - packet->size()) / 4);
433
434   std::list<uint16>::const_iterator it = nack->nack_list.begin();
435   while (it != nack->nack_list.end() &&
436          number_of_nack_fields < max_number_of_nack_fields) {
437     uint16 nack_sequence_number = *it;
438     uint16 bitmask = 0;
439     ++it;
440     while (it != nack->nack_list.end()) {
441       int shift = static_cast<uint16>(*it - nack_sequence_number) - 1;
442       if (shift >= 0 && shift <= 15) {
443         bitmask |= (1 << shift);
444         ++it;
445       } else {
446         break;
447       }
448     }
449     // Write the sequence number and the bitmask to the packet.
450     start_size = packet->size();
451     DCHECK_LT(start_size + 4, kMaxIpPacketSize) << "Not enough buffer space";
452     if (start_size + 4 > kMaxIpPacketSize) return;
453
454     packet->resize(start_size + 4);
455     net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
456     big_endian_nack_writer.WriteU16(nack_sequence_number);
457     big_endian_nack_writer.WriteU16(bitmask);
458     number_of_nack_fields++;
459   }
460   DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields);
461   (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields);
462 }
463
464 void RtcpSender::BuildBye(Packet* packet) const {
465   size_t start_size = packet->size();
466   DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space";
467   if (start_size + 8 > kMaxIpPacketSize) return;
468
469   packet->resize(start_size + 8);
470
471   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
472   big_endian_writer.WriteU8(0x80 + 1);
473   big_endian_writer.WriteU8(transport::kPacketTypeBye);
474   big_endian_writer.WriteU16(1);      // Length.
475   big_endian_writer.WriteU32(ssrc_);  // Add our own SSRC.
476 }
477
478 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
479                            Packet* packet) const {
480   size_t start_size = packet->size();
481   DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
482   if (start_size + 20 > kMaxIpPacketSize) return;
483
484   packet->resize(start_size + 20);
485
486   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
487
488   big_endian_writer.WriteU8(0x80);
489   big_endian_writer.WriteU8(transport::kPacketTypeXr);
490   big_endian_writer.WriteU16(4);      // Length.
491   big_endian_writer.WriteU32(ssrc_);  // Add our own SSRC.
492   big_endian_writer.WriteU8(4);       // Add block type.
493   big_endian_writer.WriteU8(0);       // Add reserved.
494   big_endian_writer.WriteU16(2);      // Block length.
495
496   // Add the media (received RTP) SSRC.
497   big_endian_writer.WriteU32(rrtr->ntp_seconds);
498   big_endian_writer.WriteU32(rrtr->ntp_fraction);
499 }
500
501 void RtcpSender::BuildCast(const RtcpCastMessage* cast, Packet* packet) const {
502   size_t start_size = packet->size();
503   DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
504   if (start_size + 20 > kMaxIpPacketSize) return;
505
506   packet->resize(start_size + 20);
507
508   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
509   uint8 FMT = 15;  // Application layer feedback.
510   big_endian_writer.WriteU8(0x80 + FMT);
511   big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
512   big_endian_writer.WriteU8(0);
513   size_t cast_size_pos = start_size + 3;  // Save length position.
514   big_endian_writer.WriteU8(4);
515   big_endian_writer.WriteU32(ssrc_);              // Add our own SSRC.
516   big_endian_writer.WriteU32(cast->media_ssrc_);  // Remote SSRC.
517   big_endian_writer.WriteU32(kCast);
518   big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_));
519   size_t cast_loss_field_pos = start_size + 17;  // Save loss field position.
520   big_endian_writer.WriteU8(0);  // Overwritten with number_of_loss_fields.
521   big_endian_writer.WriteU8(0);  // Reserved.
522   big_endian_writer.WriteU8(0);  // Reserved.
523
524   size_t number_of_loss_fields = 0;
525   size_t max_number_of_loss_fields = std::min<size_t>(
526       kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4);
527
528   MissingFramesAndPacketsMap::const_iterator frame_it =
529       cast->missing_frames_and_packets_.begin();
530
531   for (; frame_it != cast->missing_frames_and_packets_.end() &&
532              number_of_loss_fields < max_number_of_loss_fields;
533        ++frame_it) {
534     // Iterate through all frames with missing packets.
535     if (frame_it->second.empty()) {
536       // Special case all packets in a frame is missing.
537       start_size = packet->size();
538       packet->resize(start_size + 4);
539       net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
540       big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
541       big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost);
542       big_endian_nack_writer.WriteU8(0);
543       ++number_of_loss_fields;
544     } else {
545       PacketIdSet::const_iterator packet_it = frame_it->second.begin();
546       while (packet_it != frame_it->second.end()) {
547         uint16 packet_id = *packet_it;
548
549         start_size = packet->size();
550         packet->resize(start_size + 4);
551         net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]),
552                                                     4);
553
554         // Write frame and packet id to buffer before calculating bitmask.
555         big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
556         big_endian_nack_writer.WriteU16(packet_id);
557
558         uint8 bitmask = 0;
559         ++packet_it;
560         while (packet_it != frame_it->second.end()) {
561           int shift = static_cast<uint8>(*packet_it - packet_id) - 1;
562           if (shift >= 0 && shift <= 7) {
563             bitmask |= (1 << shift);
564             ++packet_it;
565           } else {
566             break;
567           }
568         }
569         big_endian_nack_writer.WriteU8(bitmask);
570         ++number_of_loss_fields;
571       }
572     }
573   }
574   DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields);
575   (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields);
576   (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields);
577 }
578
579 void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
580                                   Packet* packet) const {
581   DCHECK(receiver_log_message);
582   const size_t packet_start_size = packet->size();
583   size_t number_of_frames = 0;
584   size_t total_number_of_messages_to_send = 0;
585   size_t rtcp_log_size = 0;
586
587   if (!ScanRtcpReceiverLogMessage(
588            *receiver_log_message, packet_start_size, &number_of_frames,
589            &total_number_of_messages_to_send, &rtcp_log_size)) {
590     return;
591   }
592   packet->resize(packet_start_size + rtcp_log_size);
593
594   net::BigEndianWriter big_endian_writer(&((*packet)[packet_start_size]),
595                                          rtcp_log_size);
596   big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype);
597   big_endian_writer.WriteU8(transport::kPacketTypeApplicationDefined);
598   big_endian_writer.WriteU16(static_cast<uint16>(
599       2 + 2 * number_of_frames + total_number_of_messages_to_send));
600   big_endian_writer.WriteU32(ssrc_);  // Add our own SSRC.
601   big_endian_writer.WriteU32(kCast);
602
603   while (!receiver_log_message->empty() &&
604          total_number_of_messages_to_send > 0) {
605     RtcpReceiverFrameLogMessage& frame_log_messages(
606         receiver_log_message->front());
607
608     // Add our frame header.
609     big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_);
610     size_t messages_in_frame = frame_log_messages.event_log_messages_.size();
611     if (messages_in_frame > total_number_of_messages_to_send) {
612       // We are running out of space.
613       messages_in_frame = total_number_of_messages_to_send;
614     }
615     // Keep track of how many messages we have left to send.
616     total_number_of_messages_to_send -= messages_in_frame;
617
618     // On the wire format is number of messages - 1.
619     big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1));
620
621     base::TimeTicks event_timestamp_base =
622         frame_log_messages.event_log_messages_.front().event_timestamp;
623     uint32 base_timestamp_ms =
624         (event_timestamp_base - base::TimeTicks()).InMilliseconds();
625     big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16));
626     big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8));
627     big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms));
628
629     while (!frame_log_messages.event_log_messages_.empty() &&
630            messages_in_frame > 0) {
631       const RtcpReceiverEventLogMessage& event_message =
632           frame_log_messages.event_log_messages_.front();
633       uint16 event_type_and_timestamp_delta =
634           MergeEventTypeAndTimestampForWireFormat(
635               event_message.type,
636               event_message.event_timestamp - event_timestamp_base);
637       switch (event_message.type) {
638         case kAudioAckSent:
639         case kVideoAckSent:
640         case kAudioPlayoutDelay:
641         case kAudioFrameDecoded:
642         case kVideoFrameDecoded:
643         case kVideoRenderDelay:
644           big_endian_writer.WriteU16(
645               static_cast<uint16>(event_message.delay_delta.InMilliseconds()));
646           big_endian_writer.WriteU16(event_type_and_timestamp_delta);
647           break;
648         case kAudioPacketReceived:
649         case kVideoPacketReceived:
650         case kDuplicateAudioPacketReceived:
651         case kDuplicateVideoPacketReceived:
652           big_endian_writer.WriteU16(event_message.packet_id);
653           big_endian_writer.WriteU16(event_type_and_timestamp_delta);
654           break;
655         default:
656           NOTREACHED();
657       }
658       messages_in_frame--;
659       frame_log_messages.event_log_messages_.pop_front();
660     }
661     if (frame_log_messages.event_log_messages_.empty()) {
662       // We sent all messages on this frame; pop the frame header.
663       receiver_log_message->pop_front();
664     }
665   }
666   DCHECK_EQ(total_number_of_messages_to_send, 0);
667 }
668
669 }  // namespace cast
670 }  // namespace media