Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: media/cast/rtcp/rtcp_sender.cc

Issue 388663003: Cast: Reshuffle files under media/cast (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: missing includes Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/cast/rtcp/rtcp_sender.h ('k') | media/cast/rtcp/rtcp_sender_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <stdint.h>
8
9 #include <algorithm>
10 #include <vector>
11
12 #include "base/big_endian.h"
13 #include "base/logging.h"
14 #include "media/cast/cast_environment.h"
15 #include "media/cast/rtcp/rtcp_defines.h"
16 #include "media/cast/rtcp/rtcp_utility.h"
17 #include "media/cast/transport/cast_transport_defines.h"
18 #include "media/cast/transport/pacing/paced_sender.h"
19
20 namespace media {
21 namespace cast {
22 namespace {
23
24 // Max delta is 4095 milliseconds because we need to be able to encode it in
25 // 12 bits.
26 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff);
27
28 uint16 MergeEventTypeAndTimestampForWireFormat(
29 const CastLoggingEvent& event,
30 const base::TimeDelta& time_delta) {
31 int64 time_delta_ms = time_delta.InMilliseconds();
32
33 DCHECK_GE(time_delta_ms, 0);
34 DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs);
35
36 uint16 time_delta_12_bits =
37 static_cast<uint16>(time_delta_ms & kMaxWireFormatTimeDeltaMs);
38
39 uint16 event_type_4_bits = ConvertEventTypeToWireFormat(event);
40 DCHECK(event_type_4_bits);
41 DCHECK(~(event_type_4_bits & 0xfff0));
42 return (event_type_4_bits << 12) | time_delta_12_bits;
43 }
44
45 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs,
46 const RtcpReceiverEventLogMessage& rhs) {
47 return lhs.event_timestamp < rhs.event_timestamp;
48 }
49
50 void AddReceiverLog(
51 const RtcpReceiverLogMessage& redundancy_receiver_log_message,
52 RtcpReceiverLogMessage* receiver_log_message,
53 size_t* remaining_space,
54 size_t* number_of_frames,
55 size_t* total_number_of_messages_to_send) {
56 RtcpReceiverLogMessage::const_iterator it =
57 redundancy_receiver_log_message.begin();
58 while (it != redundancy_receiver_log_message.end() &&
59 *remaining_space >=
60 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
61 receiver_log_message->push_front(*it);
62 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) /
63 kRtcpReceiverEventLogSize;
64 RtcpReceiverEventLogMessages& event_log_messages =
65 receiver_log_message->front().event_log_messages_;
66 if (num_event_logs < event_log_messages.size())
67 event_log_messages.resize(num_event_logs);
68
69 *remaining_space -= kRtcpReceiverFrameLogSize +
70 event_log_messages.size() * kRtcpReceiverEventLogSize;
71 ++*number_of_frames;
72 *total_number_of_messages_to_send += event_log_messages.size();
73 ++it;
74 }
75 }
76
77 // A class to build a string representing the NACK list in Cast message.
78 //
79 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame
80 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of
81 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is
82 // completely missing will show as "26:65535".
83 class NackStringBuilder {
84 public:
85 NackStringBuilder()
86 : frame_count_(0),
87 packet_count_(0),
88 last_frame_id_(-1),
89 last_packet_id_(-1),
90 contiguous_sequence_(false) {}
91 ~NackStringBuilder() {}
92
93 bool Empty() const { return frame_count_ == 0; }
94
95 void PushFrame(int frame_id) {
96 DCHECK_GE(frame_id, 0);
97 if (frame_count_ > 0) {
98 if (frame_id == last_frame_id_) {
99 return;
100 }
101 if (contiguous_sequence_) {
102 stream_ << "-" << last_packet_id_;
103 }
104 stream_ << ", ";
105 }
106 stream_ << frame_id;
107 last_frame_id_ = frame_id;
108 packet_count_ = 0;
109 contiguous_sequence_ = false;
110 ++frame_count_;
111 }
112
113 void PushPacket(int packet_id) {
114 DCHECK_GE(last_frame_id_, 0);
115 DCHECK_GE(packet_id, 0);
116 if (packet_count_ == 0) {
117 stream_ << ":" << packet_id;
118 } else if (packet_id == last_packet_id_ + 1) {
119 contiguous_sequence_ = true;
120 } else {
121 if (contiguous_sequence_) {
122 stream_ << "-" << last_packet_id_;
123 contiguous_sequence_ = false;
124 }
125 stream_ << "," << packet_id;
126 }
127 ++packet_count_;
128 last_packet_id_ = packet_id;
129 }
130
131 std::string GetString() {
132 if (contiguous_sequence_) {
133 stream_ << "-" << last_packet_id_;
134 contiguous_sequence_ = false;
135 }
136 return stream_.str();
137 }
138
139 private:
140 std::ostringstream stream_;
141 int frame_count_;
142 int packet_count_;
143 int last_frame_id_;
144 int last_packet_id_;
145 bool contiguous_sequence_;
146 };
147 } // namespace
148
149 // TODO(mikhal): This is only used by the receiver. Consider renaming.
150 RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
151 transport::PacedPacketSender* outgoing_transport,
152 uint32 sending_ssrc,
153 const std::string& c_name)
154 : ssrc_(sending_ssrc),
155 c_name_(c_name),
156 transport_(outgoing_transport),
157 cast_environment_(cast_environment) {
158 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config";
159 }
160
161 RtcpSender::~RtcpSender() {}
162
163 void RtcpSender::SendRtcpFromRtpReceiver(
164 uint32 packet_type_flags,
165 const transport::RtcpReportBlock* report_block,
166 const RtcpReceiverReferenceTimeReport* rrtr,
167 const RtcpCastMessage* cast_message,
168 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events,
169 base::TimeDelta target_delay) {
170 if (packet_type_flags & transport::kRtcpSr ||
171 packet_type_flags & transport::kRtcpDlrr ||
172 packet_type_flags & transport::kRtcpSenderLog) {
173 NOTREACHED() << "Invalid argument";
174 }
175 if (packet_type_flags & transport::kRtcpPli ||
176 packet_type_flags & transport::kRtcpRpsi ||
177 packet_type_flags & transport::kRtcpRemb ||
178 packet_type_flags & transport::kRtcpNack) {
179 // Implement these for webrtc interop.
180 NOTIMPLEMENTED();
181 }
182 transport::PacketRef packet(new base::RefCountedData<Packet>);
183 packet->data.reserve(kMaxIpPacketSize);
184
185 if (packet_type_flags & transport::kRtcpRr) {
186 BuildRR(report_block, &packet->data);
187 if (!c_name_.empty()) {
188 BuildSdec(&packet->data);
189 }
190 }
191 if (packet_type_flags & transport::kRtcpBye) {
192 BuildBye(&packet->data);
193 }
194 if (packet_type_flags & transport::kRtcpRrtr) {
195 DCHECK(rrtr) << "Invalid argument";
196 BuildRrtr(rrtr, &packet->data);
197 }
198 if (packet_type_flags & transport::kRtcpCast) {
199 DCHECK(cast_message) << "Invalid argument";
200 BuildCast(cast_message, target_delay, &packet->data);
201 }
202 if (packet_type_flags & transport::kRtcpReceiverLog) {
203 DCHECK(rtcp_events) << "Invalid argument";
204 BuildReceiverLog(*rtcp_events, &packet->data);
205 }
206
207 if (packet->data.empty())
208 return; // Sanity don't send empty packets.
209
210 transport_->SendRtcpPacket(ssrc_, packet);
211 }
212
213 void RtcpSender::BuildRR(const transport::RtcpReportBlock* report_block,
214 Packet* packet) const {
215 size_t start_size = packet->size();
216 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space";
217 if (start_size + 32 > kMaxIpPacketSize)
218 return;
219
220 uint16 number_of_rows = (report_block) ? 7 : 1;
221 packet->resize(start_size + 8);
222
223 base::BigEndianWriter big_endian_writer(
224 reinterpret_cast<char*>(&((*packet)[start_size])), 8);
225 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
226 big_endian_writer.WriteU8(transport::kPacketTypeReceiverReport);
227 big_endian_writer.WriteU16(number_of_rows);
228 big_endian_writer.WriteU32(ssrc_);
229
230 if (report_block) {
231 AddReportBlocks(*report_block, packet); // Adds 24 bytes.
232 }
233 }
234
235 void RtcpSender::AddReportBlocks(const transport::RtcpReportBlock& report_block,
236 Packet* packet) const {
237 size_t start_size = packet->size();
238 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
239 if (start_size + 24 > kMaxIpPacketSize)
240 return;
241
242 packet->resize(start_size + 24);
243
244 base::BigEndianWriter big_endian_writer(
245 reinterpret_cast<char*>(&((*packet)[start_size])), 24);
246 big_endian_writer.WriteU32(report_block.media_ssrc);
247 big_endian_writer.WriteU8(report_block.fraction_lost);
248 big_endian_writer.WriteU8(report_block.cumulative_lost >> 16);
249 big_endian_writer.WriteU8(report_block.cumulative_lost >> 8);
250 big_endian_writer.WriteU8(report_block.cumulative_lost);
251
252 // Extended highest seq_no, contain the highest sequence number received.
253 big_endian_writer.WriteU32(report_block.extended_high_sequence_number);
254 big_endian_writer.WriteU32(report_block.jitter);
255
256 // Last SR timestamp; our NTP time when we received the last report.
257 // This is the value that we read from the send report packet not when we
258 // received it.
259 big_endian_writer.WriteU32(report_block.last_sr);
260
261 // Delay since last received report, time since we received the report.
262 big_endian_writer.WriteU32(report_block.delay_since_last_sr);
263 }
264
265 void RtcpSender::BuildSdec(Packet* packet) const {
266 size_t start_size = packet->size();
267 DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize)
268 << "Not enough buffer space";
269 if (start_size + 12 > kMaxIpPacketSize)
270 return;
271
272 // SDES Source Description.
273 packet->resize(start_size + 10);
274
275 base::BigEndianWriter big_endian_writer(
276 reinterpret_cast<char*>(&((*packet)[start_size])), 10);
277 // We always need to add one SDES CNAME.
278 big_endian_writer.WriteU8(0x80 + 1);
279 big_endian_writer.WriteU8(transport::kPacketTypeSdes);
280
281 // Handle SDES length later on.
282 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3;
283 big_endian_writer.WriteU16(0);
284 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
285 big_endian_writer.WriteU8(1); // CNAME = 1
286 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length()));
287
288 size_t sdes_length = 10 + c_name_.length();
289 packet->insert(
290 packet->end(), c_name_.c_str(), c_name_.c_str() + c_name_.length());
291
292 size_t padding = 0;
293
294 // We must have a zero field even if we have an even multiple of 4 bytes.
295 if ((packet->size() % 4) == 0) {
296 padding++;
297 packet->push_back(0);
298 }
299 while ((packet->size() % 4) != 0) {
300 padding++;
301 packet->push_back(0);
302 }
303 sdes_length += padding;
304
305 // In 32-bit words minus one and we don't count the header.
306 uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1);
307 (*packet)[sdes_length_position] = buffer_length;
308 }
309
310 void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const {
311 size_t start_size = packet->size();
312 DCHECK_LT(start_size + 12, kMaxIpPacketSize) << "Not enough buffer space";
313 if (start_size + 12 > kMaxIpPacketSize)
314 return;
315
316 packet->resize(start_size + 12);
317
318 base::BigEndianWriter big_endian_writer(
319 reinterpret_cast<char*>(&((*packet)[start_size])), 12);
320 uint8 FMT = 1; // Picture loss indicator.
321 big_endian_writer.WriteU8(0x80 + FMT);
322 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
323 big_endian_writer.WriteU16(2); // Used fixed length of 2.
324 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
325 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC.
326 }
327
328 /*
329 0 1 2 3
330 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
331 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
332 | PB |0| Payload Type| Native Rpsi bit string |
333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334 | defined per codec ... | Padding (0) |
335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336 */
337 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, Packet* packet) const {
338 size_t start_size = packet->size();
339 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space";
340 if (start_size + 24 > kMaxIpPacketSize)
341 return;
342
343 packet->resize(start_size + 24);
344
345 base::BigEndianWriter big_endian_writer(
346 reinterpret_cast<char*>(&((*packet)[start_size])), 24);
347 uint8 FMT = 3; // Reference Picture Selection Indication.
348 big_endian_writer.WriteU8(0x80 + FMT);
349 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
350
351 // Calculate length.
352 uint32 bits_required = 7;
353 uint8 bytes_required = 1;
354 while ((rpsi->picture_id >> bits_required) > 0) {
355 bits_required += 7;
356 bytes_required++;
357 }
358 uint8 size = 3;
359 if (bytes_required > 6) {
360 size = 5;
361 } else if (bytes_required > 2) {
362 size = 4;
363 }
364 big_endian_writer.WriteU8(0);
365 big_endian_writer.WriteU8(size);
366 big_endian_writer.WriteU32(ssrc_);
367 big_endian_writer.WriteU32(rpsi->remote_ssrc);
368
369 uint8 padding_bytes = 4 - ((2 + bytes_required) % 4);
370 if (padding_bytes == 4) {
371 padding_bytes = 0;
372 }
373 // Add padding length in bits, padding can be 0, 8, 16 or 24.
374 big_endian_writer.WriteU8(padding_bytes * 8);
375 big_endian_writer.WriteU8(rpsi->payload_type);
376
377 // Add picture ID.
378 for (int i = bytes_required - 1; i > 0; i--) {
379 big_endian_writer.WriteU8(0x80 |
380 static_cast<uint8>(rpsi->picture_id >> (i * 7)));
381 }
382 // Add last byte of picture ID.
383 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f));
384
385 // Add padding.
386 for (int j = 0; j < padding_bytes; ++j) {
387 big_endian_writer.WriteU8(0);
388 }
389 }
390
391 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, Packet* packet) const {
392 size_t start_size = packet->size();
393 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size();
394 DCHECK_LT(start_size + remb_size, kMaxIpPacketSize)
395 << "Not enough buffer space";
396 if (start_size + remb_size > kMaxIpPacketSize)
397 return;
398
399 packet->resize(start_size + remb_size);
400
401 base::BigEndianWriter big_endian_writer(
402 reinterpret_cast<char*>(&((*packet)[start_size])), remb_size);
403
404 // Add application layer feedback.
405 uint8 FMT = 15;
406 big_endian_writer.WriteU8(0x80 + FMT);
407 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
408 big_endian_writer.WriteU8(0);
409 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4));
410 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
411 big_endian_writer.WriteU32(0); // Remote SSRC must be 0.
412 big_endian_writer.WriteU32(kRemb);
413 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size()));
414
415 // 6 bit exponent and a 18 bit mantissa.
416 uint8 bitrate_exponent;
417 uint32 bitrate_mantissa;
418 BitrateToRembExponentBitrate(
419 remb->remb_bitrate, &bitrate_exponent, &bitrate_mantissa);
420
421 big_endian_writer.WriteU8(static_cast<uint8>(
422 (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03)));
423 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8));
424 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa));
425
426 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin();
427 for (; it != remb->remb_ssrcs.end(); ++it) {
428 big_endian_writer.WriteU32(*it);
429 }
430 }
431
432 void RtcpSender::BuildNack(const RtcpNackMessage* nack, Packet* packet) const {
433 size_t start_size = packet->size();
434 DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space";
435 if (start_size + 16 > kMaxIpPacketSize)
436 return;
437
438 packet->resize(start_size + 16);
439
440 base::BigEndianWriter big_endian_writer(
441 reinterpret_cast<char*>(&((*packet)[start_size])), 16);
442
443 uint8 FMT = 1;
444 big_endian_writer.WriteU8(0x80 + FMT);
445 big_endian_writer.WriteU8(transport::kPacketTypeGenericRtpFeedback);
446 big_endian_writer.WriteU8(0);
447 size_t nack_size_pos = start_size + 3;
448 big_endian_writer.WriteU8(3);
449 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
450 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC.
451
452 // Build NACK bitmasks and write them to the Rtcp message.
453 // The nack list should be sorted and not contain duplicates.
454 size_t number_of_nack_fields = 0;
455 size_t max_number_of_nack_fields = std::min<size_t>(
456 kRtcpMaxNackFields, (kMaxIpPacketSize - packet->size()) / 4);
457
458 std::list<uint16>::const_iterator it = nack->nack_list.begin();
459 while (it != nack->nack_list.end() &&
460 number_of_nack_fields < max_number_of_nack_fields) {
461 uint16 nack_sequence_number = *it;
462 uint16 bitmask = 0;
463 ++it;
464 while (it != nack->nack_list.end()) {
465 int shift = static_cast<uint16>(*it - nack_sequence_number) - 1;
466 if (shift >= 0 && shift <= 15) {
467 bitmask |= (1 << shift);
468 ++it;
469 } else {
470 break;
471 }
472 }
473 // Write the sequence number and the bitmask to the packet.
474 start_size = packet->size();
475 DCHECK_LT(start_size + 4, kMaxIpPacketSize) << "Not enough buffer space";
476 if (start_size + 4 > kMaxIpPacketSize)
477 return;
478
479 packet->resize(start_size + 4);
480 base::BigEndianWriter big_endian_nack_writer(
481 reinterpret_cast<char*>(&((*packet)[start_size])), 4);
482 big_endian_nack_writer.WriteU16(nack_sequence_number);
483 big_endian_nack_writer.WriteU16(bitmask);
484 number_of_nack_fields++;
485 }
486 DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields);
487 (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields);
488 }
489
490 void RtcpSender::BuildBye(Packet* packet) const {
491 size_t start_size = packet->size();
492 DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space";
493 if (start_size + 8 > kMaxIpPacketSize)
494 return;
495
496 packet->resize(start_size + 8);
497
498 base::BigEndianWriter big_endian_writer(
499 reinterpret_cast<char*>(&((*packet)[start_size])), 8);
500 big_endian_writer.WriteU8(0x80 + 1);
501 big_endian_writer.WriteU8(transport::kPacketTypeBye);
502 big_endian_writer.WriteU16(1); // Length.
503 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
504 }
505
506 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
507 Packet* packet) const {
508 size_t start_size = packet->size();
509 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
510 if (start_size + 20 > kMaxIpPacketSize)
511 return;
512
513 packet->resize(start_size + 20);
514
515 base::BigEndianWriter big_endian_writer(
516 reinterpret_cast<char*>(&((*packet)[start_size])), 20);
517
518 big_endian_writer.WriteU8(0x80);
519 big_endian_writer.WriteU8(transport::kPacketTypeXr);
520 big_endian_writer.WriteU16(4); // Length.
521 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
522 big_endian_writer.WriteU8(4); // Add block type.
523 big_endian_writer.WriteU8(0); // Add reserved.
524 big_endian_writer.WriteU16(2); // Block length.
525
526 // Add the media (received RTP) SSRC.
527 big_endian_writer.WriteU32(rrtr->ntp_seconds);
528 big_endian_writer.WriteU32(rrtr->ntp_fraction);
529 }
530
531 void RtcpSender::BuildCast(const RtcpCastMessage* cast,
532 base::TimeDelta target_delay,
533 Packet* packet) const {
534 size_t start_size = packet->size();
535 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space";
536 if (start_size + 20 > kMaxIpPacketSize)
537 return;
538
539 packet->resize(start_size + 20);
540
541 base::BigEndianWriter big_endian_writer(
542 reinterpret_cast<char*>(&((*packet)[start_size])), 20);
543 uint8 FMT = 15; // Application layer feedback.
544 big_endian_writer.WriteU8(0x80 + FMT);
545 big_endian_writer.WriteU8(transport::kPacketTypePayloadSpecific);
546 big_endian_writer.WriteU8(0);
547 size_t cast_size_pos = start_size + 3; // Save length position.
548 big_endian_writer.WriteU8(4);
549 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
550 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC.
551 big_endian_writer.WriteU32(kCast);
552 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_));
553 size_t cast_loss_field_pos = start_size + 17; // Save loss field position.
554 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields.
555 DCHECK_LE(target_delay.InMilliseconds(),
556 std::numeric_limits<uint16_t>::max());
557 big_endian_writer.WriteU16(target_delay.InMilliseconds());
558
559 size_t number_of_loss_fields = 0;
560 size_t max_number_of_loss_fields = std::min<size_t>(
561 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4);
562
563 MissingFramesAndPacketsMap::const_iterator frame_it =
564 cast->missing_frames_and_packets_.begin();
565
566 NackStringBuilder nack_string_builder;
567 for (; frame_it != cast->missing_frames_and_packets_.end() &&
568 number_of_loss_fields < max_number_of_loss_fields;
569 ++frame_it) {
570 nack_string_builder.PushFrame(frame_it->first);
571 // Iterate through all frames with missing packets.
572 if (frame_it->second.empty()) {
573 // Special case all packets in a frame is missing.
574 start_size = packet->size();
575 packet->resize(start_size + 4);
576 base::BigEndianWriter big_endian_nack_writer(
577 reinterpret_cast<char*>(&((*packet)[start_size])), 4);
578 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
579 big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost);
580 big_endian_nack_writer.WriteU8(0);
581 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost);
582 ++number_of_loss_fields;
583 } else {
584 PacketIdSet::const_iterator packet_it = frame_it->second.begin();
585 while (packet_it != frame_it->second.end()) {
586 uint16 packet_id = *packet_it;
587
588 start_size = packet->size();
589 packet->resize(start_size + 4);
590 base::BigEndianWriter big_endian_nack_writer(
591 reinterpret_cast<char*>(&((*packet)[start_size])), 4);
592
593 // Write frame and packet id to buffer before calculating bitmask.
594 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
595 big_endian_nack_writer.WriteU16(packet_id);
596 nack_string_builder.PushPacket(packet_id);
597
598 uint8 bitmask = 0;
599 ++packet_it;
600 while (packet_it != frame_it->second.end()) {
601 int shift = static_cast<uint8>(*packet_it - packet_id) - 1;
602 if (shift >= 0 && shift <= 7) {
603 nack_string_builder.PushPacket(*packet_it);
604 bitmask |= (1 << shift);
605 ++packet_it;
606 } else {
607 break;
608 }
609 }
610 big_endian_nack_writer.WriteU8(bitmask);
611 ++number_of_loss_fields;
612 }
613 }
614 }
615 VLOG_IF(1, !nack_string_builder.Empty())
616 << "SSRC: " << cast->media_ssrc_
617 << ", ACK: " << cast->ack_frame_id_
618 << ", NACK: " << nack_string_builder.GetString();
619 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields);
620 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields);
621 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields);
622 }
623
624 void RtcpSender::BuildReceiverLog(
625 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
626 Packet* packet) {
627 const size_t packet_start_size = packet->size();
628 size_t number_of_frames = 0;
629 size_t total_number_of_messages_to_send = 0;
630 size_t rtcp_log_size = 0;
631 RtcpReceiverLogMessage receiver_log_message;
632
633 if (!BuildRtcpReceiverLogMessage(rtcp_events,
634 packet_start_size,
635 &receiver_log_message,
636 &number_of_frames,
637 &total_number_of_messages_to_send,
638 &rtcp_log_size)) {
639 return;
640 }
641 packet->resize(packet_start_size + rtcp_log_size);
642
643 base::BigEndianWriter big_endian_writer(
644 reinterpret_cast<char*>(&((*packet)[packet_start_size])), rtcp_log_size);
645 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype);
646 big_endian_writer.WriteU8(transport::kPacketTypeApplicationDefined);
647 big_endian_writer.WriteU16(static_cast<uint16>(
648 2 + 2 * number_of_frames + total_number_of_messages_to_send));
649 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
650 big_endian_writer.WriteU32(kCast);
651
652 while (!receiver_log_message.empty() &&
653 total_number_of_messages_to_send > 0) {
654 RtcpReceiverFrameLogMessage& frame_log_messages(
655 receiver_log_message.front());
656
657 // Add our frame header.
658 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_);
659 size_t messages_in_frame = frame_log_messages.event_log_messages_.size();
660 if (messages_in_frame > total_number_of_messages_to_send) {
661 // We are running out of space.
662 messages_in_frame = total_number_of_messages_to_send;
663 }
664 // Keep track of how many messages we have left to send.
665 total_number_of_messages_to_send -= messages_in_frame;
666
667 // On the wire format is number of messages - 1.
668 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1));
669
670 base::TimeTicks event_timestamp_base =
671 frame_log_messages.event_log_messages_.front().event_timestamp;
672 uint32 base_timestamp_ms =
673 (event_timestamp_base - base::TimeTicks()).InMilliseconds();
674 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16));
675 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8));
676 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms));
677
678 while (!frame_log_messages.event_log_messages_.empty() &&
679 messages_in_frame > 0) {
680 const RtcpReceiverEventLogMessage& event_message =
681 frame_log_messages.event_log_messages_.front();
682 uint16 event_type_and_timestamp_delta =
683 MergeEventTypeAndTimestampForWireFormat(
684 event_message.type,
685 event_message.event_timestamp - event_timestamp_base);
686 switch (event_message.type) {
687 case FRAME_ACK_SENT:
688 case FRAME_PLAYOUT:
689 case FRAME_DECODED:
690 big_endian_writer.WriteU16(
691 static_cast<uint16>(event_message.delay_delta.InMilliseconds()));
692 big_endian_writer.WriteU16(event_type_and_timestamp_delta);
693 break;
694 case PACKET_RECEIVED:
695 big_endian_writer.WriteU16(event_message.packet_id);
696 big_endian_writer.WriteU16(event_type_and_timestamp_delta);
697 break;
698 default:
699 NOTREACHED();
700 }
701 messages_in_frame--;
702 frame_log_messages.event_log_messages_.pop_front();
703 }
704 if (frame_log_messages.event_log_messages_.empty()) {
705 // We sent all messages on this frame; pop the frame header.
706 receiver_log_message.pop_front();
707 }
708 }
709 DCHECK_EQ(total_number_of_messages_to_send, 0u);
710 }
711
712 bool RtcpSender::BuildRtcpReceiverLogMessage(
713 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
714 size_t start_size,
715 RtcpReceiverLogMessage* receiver_log_message,
716 size_t* number_of_frames,
717 size_t* total_number_of_messages_to_send,
718 size_t* rtcp_log_size) {
719 size_t remaining_space =
720 std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size);
721 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
722 kRtcpReceiverEventLogSize) {
723 return false;
724 }
725
726 // We use this to do event timestamp sorting and truncating for events of
727 // a single frame.
728 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages;
729
730 // Account for the RTCP header for an application-defined packet.
731 remaining_space -= kRtcpCastLogHeaderSize;
732
733 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit =
734 rtcp_events.rbegin();
735
736 while (rit != rtcp_events.rend() &&
737 remaining_space >=
738 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
739 const RtpTimestamp rtp_timestamp = rit->first;
740 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
741 remaining_space -= kRtcpReceiverFrameLogSize;
742 ++*number_of_frames;
743
744 // Get all events of a single frame.
745 sorted_log_messages.clear();
746 do {
747 RtcpReceiverEventLogMessage event_log_message;
748 event_log_message.type = rit->second.type;
749 event_log_message.event_timestamp = rit->second.timestamp;
750 event_log_message.delay_delta = rit->second.delay_delta;
751 event_log_message.packet_id = rit->second.packet_id;
752 sorted_log_messages.push_back(event_log_message);
753 ++rit;
754 } while (rit != rtcp_events.rend() && rit->first == rtp_timestamp);
755
756 std::sort(sorted_log_messages.begin(),
757 sorted_log_messages.end(),
758 &EventTimestampLessThan);
759
760 // From |sorted_log_messages|, only take events that are no greater than
761 // |kMaxWireFormatTimeDeltaMs| seconds away from the latest event. Events
762 // older than that cannot be encoded over the wire.
763 std::vector<RtcpReceiverEventLogMessage>::reverse_iterator sorted_rit =
764 sorted_log_messages.rbegin();
765 base::TimeTicks first_event_timestamp = sorted_rit->event_timestamp;
766 size_t events_in_frame = 0;
767 while (sorted_rit != sorted_log_messages.rend() &&
768 events_in_frame < kRtcpMaxReceiverLogMessages &&
769 remaining_space >= kRtcpReceiverEventLogSize) {
770 base::TimeDelta delta(first_event_timestamp -
771 sorted_rit->event_timestamp);
772 if (delta.InMilliseconds() > kMaxWireFormatTimeDeltaMs)
773 break;
774 frame_log.event_log_messages_.push_front(*sorted_rit);
775 ++events_in_frame;
776 ++*total_number_of_messages_to_send;
777 remaining_space -= kRtcpReceiverEventLogSize;
778 ++sorted_rit;
779 }
780
781 receiver_log_message->push_front(frame_log);
782 }
783
784 rtcp_events_history_.push_front(*receiver_log_message);
785
786 // We don't try to match RTP timestamps of redundancy frame logs with those
787 // from the newest set (which would save the space of an extra RTP timestamp
788 // over the wire). Unless the redundancy frame logs are very recent, it's
789 // unlikely there will be a match anyway.
790 if (rtcp_events_history_.size() > kFirstRedundancyOffset) {
791 // Add first redundnacy messages, if enough space remaining
792 AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset],
793 receiver_log_message,
794 &remaining_space,
795 number_of_frames,
796 total_number_of_messages_to_send);
797 }
798
799 if (rtcp_events_history_.size() > kSecondRedundancyOffset) {
800 // Add second redundancy messages, if enough space remaining
801 AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset],
802 receiver_log_message,
803 &remaining_space,
804 number_of_frames,
805 total_number_of_messages_to_send);
806 }
807
808 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) {
809 rtcp_events_history_.pop_back();
810 }
811
812 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize);
813
814 *rtcp_log_size =
815 kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize +
816 *total_number_of_messages_to_send * kRtcpReceiverEventLogSize;
817 DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size)
818 << "Not enough buffer space.";
819
820 VLOG(3) << "number of frames: " << *number_of_frames;
821 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send;
822 VLOG(3) << "rtcp log size: " << *rtcp_log_size;
823 return *number_of_frames > 0;
824 }
825
826 } // namespace cast
827 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/rtcp/rtcp_sender.h ('k') | media/cast/rtcp/rtcp_sender_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698