Cast: Split kDuplicatePacketReceived into separate events for audio/video.
[chromium-blink-merge.git] / media / cast / rtcp / rtcp_sender.cc
blobaf9042f4f498293003983589fceae8b33a336508
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"
7 #include <algorithm>
8 #include <vector>
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"
19 namespace {
21 using media::cast::kRtcpCastLogHeaderSize;
22 using media::cast::kRtcpSenderFrameLogSize;
23 using media::cast::kRtcpReceiverFrameLogSize;
24 using media::cast::kRtcpReceiverEventLogSize;
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.
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);
61 uint16 event_type_and_timestamp_delta =
62 static_cast<uint16>(time_delta_ms & 0xfff);
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;
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;
76 size_t remaining_space = media::cast::kMaxIpPacketSize - start_size;
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";
84 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
85 kRtcpReceiverEventLogSize) {
86 return false;
88 // Account for the RTCP header for an application-defined packet.
89 remaining_space -= kRtcpCastLogHeaderSize;
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)++;
96 remaining_space -= kRtcpReceiverFrameLogSize;
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;
111 remaining_space -= messages_to_send * kRtcpReceiverEventLogSize;
112 *total_number_of_messages_to_send += messages_to_send;
114 if (remaining_space <
115 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
116 // Make sure that we have room for at least one more message.
117 break;
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";
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;
131 } // namespace
133 namespace media {
134 namespace cast {
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";
147 RtcpSender::~RtcpSender() {}
149 // static
150 bool RtcpSender::IsReceiverEvent(const media::cast::CastLoggingEvent& event) {
151 return ConvertEventTypeToWireFormat(event) != 0;
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";
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();
169 Packet packet;
170 packet.reserve(kMaxIpPacketSize);
172 if (packet_type_flags & kRtcpRr) {
173 BuildRR(report_block, &packet);
174 if (!c_name_.empty()) {
175 BuildSdec(&packet);
178 if (packet_type_flags & kRtcpBye) {
179 BuildBye(&packet);
181 if (packet_type_flags & kRtcpRrtr) {
182 DCHECK(rrtr) << "Invalid argument";
183 BuildRrtr(rrtr, &packet);
185 if (packet_type_flags & kRtcpCast) {
186 DCHECK(cast_message) << "Invalid argument";
187 BuildCast(cast_message, &packet);
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);
195 if (packet.empty()) return; // Sanity don't send empty packets.
197 transport_->SendRtcpPacket(packet);
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;
206 uint16 number_of_rows = (report_block) ? 7 : 1;
207 packet->resize(start_size + 8);
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_);
215 if (report_block) {
216 AddReportBlocks(*report_block, packet); // Adds 24 bytes.
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;
226 packet->resize(start_size + 24);
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);
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);
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);
244 // Delay since last received report, time since we received the report.
245 big_endian_writer.WriteU32(report_block.delay_since_last_sr);
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;
254 // SDES Source Description.
255 packet->resize(start_size + 10);
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);
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()));
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());
273 size_t padding = 0;
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);
280 while ((packet->size() % 4) != 0) {
281 padding++;
282 packet->push_back(0);
284 sdes_length += padding;
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;
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;
296 packet->resize(start_size + 12);
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.
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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;
321 packet->resize(start_size + 24);
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);
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++;
335 uint8 size = 3;
336 if (bytes_required > 6) {
337 size = 5;
338 } else if (bytes_required > 2) {
339 size = 4;
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);
346 uint8 padding_bytes = 4 - ((2 + bytes_required) % 4);
347 if (padding_bytes == 4) {
348 padding_bytes = 0;
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);
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)));
359 // Add last byte of picture ID.
360 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f));
362 // Add padding.
363 for (int j = 0; j < padding_bytes; ++j) {
364 big_endian_writer.WriteU8(0);
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;
375 packet->resize(start_size + remb_size);
377 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size);
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()));
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);
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));
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);
405 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
406 cast_environment_->Logging()->InsertGenericEvent(now, kRembBitrate,
407 remb->remb_bitrate);
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;
415 packet->resize(start_size + 16);
417 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16);
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.
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);
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;
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;
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++;
460 DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields);
461 (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields);
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;
469 packet->resize(start_size + 8);
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.
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;
484 packet->resize(start_size + 20);
486 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
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.
496 // Add the media (received RTP) SSRC.
497 big_endian_writer.WriteU32(rrtr->ntp_seconds);
498 big_endian_writer.WriteU32(rrtr->ntp_fraction);
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;
506 packet->resize(start_size + 20);
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.
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);
528 MissingFramesAndPacketsMap::const_iterator frame_it =
529 cast->missing_frames_and_packets_.begin();
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;
549 start_size = packet->size();
550 packet->resize(start_size + 4);
551 net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]),
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);
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;
569 big_endian_nack_writer.WriteU8(bitmask);
570 ++number_of_loss_fields;
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);
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;
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;
592 packet->resize(packet_start_size + rtcp_log_size);
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);
603 while (!receiver_log_message->empty() &&
604 total_number_of_messages_to_send > 0) {
605 RtcpReceiverFrameLogMessage& frame_log_messages(
606 receiver_log_message->front());
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;
615 // Keep track of how many messages we have left to send.
616 total_number_of_messages_to_send -= messages_in_frame;
618 // On the wire format is number of messages - 1.
619 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1));
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));
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();
658 messages_in_frame--;
659 frame_log_messages.event_log_messages_.pop_front();
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();
666 DCHECK_EQ(total_number_of_messages_to_send, 0);
669 } // namespace cast
670 } // namespace media