OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/rtcp/rtcp_sender.h" | 5 #include "media/cast/net/rtcp/rtcp_sender.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <vector> | 10 #include <vector> |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 std::ostringstream stream_; | 139 std::ostringstream stream_; |
140 int frame_count_; | 140 int frame_count_; |
141 int packet_count_; | 141 int packet_count_; |
142 int last_frame_id_; | 142 int last_frame_id_; |
143 int last_packet_id_; | 143 int last_packet_id_; |
144 bool contiguous_sequence_; | 144 bool contiguous_sequence_; |
145 }; | 145 }; |
146 } // namespace | 146 } // namespace |
147 | 147 |
148 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, | 148 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, |
149 uint32 sending_ssrc, | 149 uint32 sending_ssrc) |
150 const std::string& c_name) | |
151 : ssrc_(sending_ssrc), | 150 : ssrc_(sending_ssrc), |
152 c_name_(c_name), | |
153 transport_(outgoing_transport) { | 151 transport_(outgoing_transport) { |
154 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config"; | |
155 } | 152 } |
156 | 153 |
157 RtcpSender::~RtcpSender() {} | 154 RtcpSender::~RtcpSender() {} |
158 | 155 |
159 void RtcpSender::SendRtcpFromRtpReceiver( | 156 void RtcpSender::SendRtcpFromRtpReceiver( |
160 uint32 packet_type_flags, | 157 uint32 packet_type_flags, |
161 const RtcpReportBlock* report_block, | 158 const RtcpReportBlock* report_block, |
162 const RtcpReceiverReferenceTimeReport* rrtr, | 159 const RtcpReceiverReferenceTimeReport* rrtr, |
163 const RtcpCastMessage* cast_message, | 160 const RtcpCastMessage* cast_message, |
164 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, | 161 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, |
165 base::TimeDelta target_delay) { | 162 base::TimeDelta target_delay) { |
166 if (packet_type_flags & kRtcpSr || | 163 if (packet_type_flags & kRtcpDlrr) { |
167 packet_type_flags & kRtcpDlrr || | |
168 packet_type_flags & kRtcpSenderLog) { | |
169 NOTREACHED() << "Invalid argument"; | 164 NOTREACHED() << "Invalid argument"; |
170 } | 165 } |
171 if (packet_type_flags & kRtcpPli || | |
172 packet_type_flags & kRtcpRpsi || | |
173 packet_type_flags & kRtcpRemb || | |
174 packet_type_flags & kRtcpNack) { | |
175 // Implement these for webrtc interop. | |
176 NOTIMPLEMENTED(); | |
177 } | |
178 PacketRef packet(new base::RefCountedData<Packet>); | 166 PacketRef packet(new base::RefCountedData<Packet>); |
179 packet->data.reserve(kMaxIpPacketSize); | 167 packet->data.reserve(kMaxIpPacketSize); |
180 if (packet_type_flags & kRtcpRr) { | 168 if (packet_type_flags & kRtcpRr) { |
181 BuildRR(report_block, &packet->data); | 169 BuildRR(report_block, &packet->data); |
182 if (!c_name_.empty()) { | |
183 BuildSdec(&packet->data); | |
184 } | |
185 } | |
186 if (packet_type_flags & kRtcpBye) { | |
187 BuildBye(&packet->data); | |
188 } | 170 } |
189 if (packet_type_flags & kRtcpRrtr) { | 171 if (packet_type_flags & kRtcpRrtr) { |
190 DCHECK(rrtr) << "Invalid argument"; | 172 DCHECK(rrtr) << "Invalid argument"; |
191 BuildRrtr(rrtr, &packet->data); | 173 BuildRrtr(rrtr, &packet->data); |
192 } | 174 } |
193 if (packet_type_flags & kRtcpCast) { | 175 if (packet_type_flags & kRtcpCast) { |
194 DCHECK(cast_message) << "Invalid argument"; | 176 DCHECK(cast_message) << "Invalid argument"; |
195 BuildCast(cast_message, target_delay, &packet->data); | 177 BuildCast(cast_message, target_delay, &packet->data); |
196 } | 178 } |
197 if (packet_type_flags & kRtcpReceiverLog) { | 179 if (packet_type_flags & kRtcpReceiverLog) { |
198 DCHECK(rtcp_events) << "Invalid argument"; | 180 DCHECK(rtcp_events) << "Invalid argument"; |
199 BuildReceiverLog(*rtcp_events, &packet->data); | 181 BuildReceiverLog(*rtcp_events, &packet->data); |
200 } | 182 } |
201 | 183 |
202 if (packet->data.empty()) { | 184 if (packet->data.empty()) { |
203 NOTREACHED() << "Empty packet."; | 185 NOTREACHED() << "Empty packet."; |
204 return; // Sanity don't send empty packets. | 186 return; // Sanity don't send empty packets. |
205 } | 187 } |
206 | 188 |
207 transport_->SendRtcpPacket(ssrc_, packet); | 189 transport_->SendRtcpPacket(ssrc_, packet); |
208 } | 190 } |
209 | 191 |
210 void RtcpSender::SendRtcpFromRtpSender( | 192 void RtcpSender::SendRtcpFromRtpSender( |
211 uint32 packet_type_flags, | 193 uint32 packet_type_flags, |
212 const RtcpSenderInfo& sender_info, | 194 const RtcpSenderInfo& sender_info, |
213 const RtcpDlrrReportBlock& dlrr) { | 195 const RtcpDlrrReportBlock& dlrr) { |
214 if (packet_type_flags & kRtcpRr || | 196 if (packet_type_flags & kRtcpRr || |
215 packet_type_flags & kRtcpPli || | |
216 packet_type_flags & kRtcpRrtr || | 197 packet_type_flags & kRtcpRrtr || |
217 packet_type_flags & kRtcpCast || | 198 packet_type_flags & kRtcpCast || |
218 packet_type_flags & kRtcpReceiverLog || | 199 packet_type_flags & kRtcpReceiverLog) { |
219 packet_type_flags & kRtcpRpsi || | |
220 packet_type_flags & kRtcpRemb || | |
221 packet_type_flags & kRtcpNack) { | |
222 NOTREACHED() << "Invalid argument"; | 200 NOTREACHED() << "Invalid argument"; |
223 } | 201 } |
224 PacketRef packet(new base::RefCountedData<Packet>); | 202 PacketRef packet(new base::RefCountedData<Packet>); |
225 packet->data.reserve(kMaxIpPacketSize); | 203 packet->data.reserve(kMaxIpPacketSize); |
226 if (packet_type_flags & kRtcpSr) { | 204 if (packet_type_flags & kRtcpSr) { |
227 BuildSR(sender_info, &packet->data); | 205 BuildSR(sender_info, &packet->data); |
228 BuildSdec(&packet->data); | |
229 } | |
230 if (packet_type_flags & kRtcpBye) { | |
231 BuildBye(&packet->data); | |
232 } | 206 } |
233 if (packet_type_flags & kRtcpDlrr) { | 207 if (packet_type_flags & kRtcpDlrr) { |
234 BuildDlrrRb(dlrr, &packet->data); | 208 BuildDlrrRb(dlrr, &packet->data); |
235 } | 209 } |
236 if (packet->data.empty()) { | 210 if (packet->data.empty()) { |
237 NOTREACHED() << "Empty packet."; | 211 NOTREACHED() << "Empty packet."; |
238 return; // Sanity - don't send empty packets. | 212 return; // Sanity - don't send empty packets. |
239 } | 213 } |
240 | 214 |
241 transport_->SendRtcpPacket(ssrc_, packet); | 215 transport_->SendRtcpPacket(ssrc_, packet); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 | 260 |
287 // Last SR timestamp; our NTP time when we received the last report. | 261 // Last SR timestamp; our NTP time when we received the last report. |
288 // This is the value that we read from the send report packet not when we | 262 // This is the value that we read from the send report packet not when we |
289 // received it. | 263 // received it. |
290 big_endian_writer.WriteU32(report_block.last_sr); | 264 big_endian_writer.WriteU32(report_block.last_sr); |
291 | 265 |
292 // Delay since last received report, time since we received the report. | 266 // Delay since last received report, time since we received the report. |
293 big_endian_writer.WriteU32(report_block.delay_since_last_sr); | 267 big_endian_writer.WriteU32(report_block.delay_since_last_sr); |
294 } | 268 } |
295 | 269 |
296 void RtcpSender::BuildSdec(Packet* packet) const { | |
297 size_t start_size = packet->size(); | |
298 DCHECK_LT(start_size + 12 + c_name_.length(), kMaxIpPacketSize) | |
299 << "Not enough buffer space"; | |
300 if (start_size + 12 > kMaxIpPacketSize) | |
301 return; | |
302 | |
303 // SDES Source Description. | |
304 packet->resize(start_size + 10); | |
305 | |
306 base::BigEndianWriter big_endian_writer( | |
307 reinterpret_cast<char*>(&((*packet)[start_size])), 10); | |
308 // We always need to add one SDES CNAME. | |
309 big_endian_writer.WriteU8(0x80 + 1); | |
310 big_endian_writer.WriteU8(kPacketTypeSdes); | |
311 | |
312 // Handle SDES length later on. | |
313 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3; | |
314 big_endian_writer.WriteU16(0); | |
315 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
316 big_endian_writer.WriteU8(1); // CNAME = 1 | |
317 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length())); | |
318 | |
319 size_t sdes_length = 10 + c_name_.length(); | |
320 packet->insert( | |
321 packet->end(), c_name_.c_str(), c_name_.c_str() + c_name_.length()); | |
322 | |
323 size_t padding = 0; | |
324 | |
325 // We must have a zero field even if we have an even multiple of 4 bytes. | |
326 if ((packet->size() % 4) == 0) { | |
327 padding++; | |
328 packet->push_back(0); | |
329 } | |
330 while ((packet->size() % 4) != 0) { | |
331 padding++; | |
332 packet->push_back(0); | |
333 } | |
334 sdes_length += padding; | |
335 | |
336 // In 32-bit words minus one and we don't count the header. | |
337 uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1); | |
338 (*packet)[sdes_length_position] = buffer_length; | |
339 } | |
340 | |
341 void RtcpSender::BuildPli(uint32 remote_ssrc, Packet* packet) const { | |
342 size_t start_size = packet->size(); | |
343 DCHECK_LT(start_size + 12, kMaxIpPacketSize) << "Not enough buffer space"; | |
344 if (start_size + 12 > kMaxIpPacketSize) | |
345 return; | |
346 | |
347 packet->resize(start_size + 12); | |
348 | |
349 base::BigEndianWriter big_endian_writer( | |
350 reinterpret_cast<char*>(&((*packet)[start_size])), 12); | |
351 uint8 FMT = 1; // Picture loss indicator. | |
352 big_endian_writer.WriteU8(0x80 + FMT); | |
353 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | |
354 big_endian_writer.WriteU16(2); // Used fixed length of 2. | |
355 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
356 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC. | |
357 } | |
358 | |
359 /* | |
360 0 1 2 3 | |
361 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 | |
362 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
363 | PB |0| Payload Type| Native Rpsi bit string | | |
364 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
365 | defined per codec ... | Padding (0) | | |
366 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
367 */ | |
368 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi, | |
369 Packet* packet) const { | |
370 size_t start_size = packet->size(); | |
371 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; | |
372 if (start_size + 24 > kMaxIpPacketSize) | |
373 return; | |
374 | |
375 packet->resize(start_size + 24); | |
376 | |
377 base::BigEndianWriter big_endian_writer( | |
378 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | |
379 uint8 FMT = 3; // Reference Picture Selection Indication. | |
380 big_endian_writer.WriteU8(0x80 + FMT); | |
381 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | |
382 | |
383 // Calculate length. | |
384 uint32 bits_required = 7; | |
385 uint8 bytes_required = 1; | |
386 while ((rpsi->picture_id >> bits_required) > 0) { | |
387 bits_required += 7; | |
388 bytes_required++; | |
389 } | |
390 uint8 size = 3; | |
391 if (bytes_required > 6) { | |
392 size = 5; | |
393 } else if (bytes_required > 2) { | |
394 size = 4; | |
395 } | |
396 big_endian_writer.WriteU8(0); | |
397 big_endian_writer.WriteU8(size); | |
398 big_endian_writer.WriteU32(ssrc_); | |
399 big_endian_writer.WriteU32(rpsi->remote_ssrc); | |
400 | |
401 uint8 padding_bytes = 4 - ((2 + bytes_required) % 4); | |
402 if (padding_bytes == 4) { | |
403 padding_bytes = 0; | |
404 } | |
405 // Add padding length in bits, padding can be 0, 8, 16 or 24. | |
406 big_endian_writer.WriteU8(padding_bytes * 8); | |
407 big_endian_writer.WriteU8(rpsi->payload_type); | |
408 | |
409 // Add picture ID. | |
410 for (int i = bytes_required - 1; i > 0; i--) { | |
411 big_endian_writer.WriteU8(0x80 | | |
412 static_cast<uint8>(rpsi->picture_id >> (i * 7))); | |
413 } | |
414 // Add last byte of picture ID. | |
415 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f)); | |
416 | |
417 // Add padding. | |
418 for (int j = 0; j < padding_bytes; ++j) { | |
419 big_endian_writer.WriteU8(0); | |
420 } | |
421 } | |
422 | |
423 void RtcpSender::BuildRemb(const RtcpRembMessage* remb, | |
424 Packet* packet) const { | |
425 size_t start_size = packet->size(); | |
426 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size(); | |
427 DCHECK_LT(start_size + remb_size, kMaxIpPacketSize) | |
428 << "Not enough buffer space"; | |
429 if (start_size + remb_size > kMaxIpPacketSize) | |
430 return; | |
431 | |
432 packet->resize(start_size + remb_size); | |
433 | |
434 base::BigEndianWriter big_endian_writer( | |
435 reinterpret_cast<char*>(&((*packet)[start_size])), remb_size); | |
436 | |
437 // Add application layer feedback. | |
438 uint8 FMT = 15; | |
439 big_endian_writer.WriteU8(0x80 + FMT); | |
440 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | |
441 big_endian_writer.WriteU8(0); | |
442 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4)); | |
443 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
444 big_endian_writer.WriteU32(0); // Remote SSRC must be 0. | |
445 big_endian_writer.WriteU32(kRemb); | |
446 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size())); | |
447 | |
448 // 6 bit exponent and a 18 bit mantissa. | |
449 uint8 bitrate_exponent; | |
450 uint32 bitrate_mantissa; | |
451 BitrateToRembExponentBitrate( | |
452 remb->remb_bitrate, &bitrate_exponent, &bitrate_mantissa); | |
453 | |
454 big_endian_writer.WriteU8(static_cast<uint8>( | |
455 (bitrate_exponent << 2) + ((bitrate_mantissa >> 16) & 0x03))); | |
456 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8)); | |
457 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa)); | |
458 | |
459 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin(); | |
460 for (; it != remb->remb_ssrcs.end(); ++it) { | |
461 big_endian_writer.WriteU32(*it); | |
462 } | |
463 } | |
464 | |
465 void RtcpSender::BuildNack(const RtcpNackMessage* nack, | |
466 Packet* packet) const { | |
467 size_t start_size = packet->size(); | |
468 DCHECK_LT(start_size + 16, kMaxIpPacketSize) << "Not enough buffer space"; | |
469 if (start_size + 16 > kMaxIpPacketSize) | |
470 return; | |
471 | |
472 packet->resize(start_size + 16); | |
473 | |
474 base::BigEndianWriter big_endian_writer( | |
475 reinterpret_cast<char*>(&((*packet)[start_size])), 16); | |
476 | |
477 uint8 FMT = 1; | |
478 big_endian_writer.WriteU8(0x80 + FMT); | |
479 big_endian_writer.WriteU8(kPacketTypeGenericRtpFeedback); | |
480 big_endian_writer.WriteU8(0); | |
481 size_t nack_size_pos = start_size + 3; | |
482 big_endian_writer.WriteU8(3); | |
483 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
484 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC. | |
485 | |
486 // Build NACK bitmasks and write them to the Rtcp message. | |
487 // The nack list should be sorted and not contain duplicates. | |
488 size_t number_of_nack_fields = 0; | |
489 size_t max_number_of_nack_fields = std::min<size_t>( | |
490 kRtcpMaxNackFields, (kMaxIpPacketSize - packet->size()) / 4); | |
491 | |
492 std::list<uint16>::const_iterator it = nack->nack_list.begin(); | |
493 while (it != nack->nack_list.end() && | |
494 number_of_nack_fields < max_number_of_nack_fields) { | |
495 uint16 nack_sequence_number = *it; | |
496 uint16 bitmask = 0; | |
497 ++it; | |
498 while (it != nack->nack_list.end()) { | |
499 int shift = static_cast<uint16>(*it - nack_sequence_number) - 1; | |
500 if (shift >= 0 && shift <= 15) { | |
501 bitmask |= (1 << shift); | |
502 ++it; | |
503 } else { | |
504 break; | |
505 } | |
506 } | |
507 // Write the sequence number and the bitmask to the packet. | |
508 start_size = packet->size(); | |
509 DCHECK_LT(start_size + 4, kMaxIpPacketSize) << "Not enough buffer space"; | |
510 if (start_size + 4 > kMaxIpPacketSize) | |
511 return; | |
512 | |
513 packet->resize(start_size + 4); | |
514 base::BigEndianWriter big_endian_nack_writer( | |
515 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | |
516 big_endian_nack_writer.WriteU16(nack_sequence_number); | |
517 big_endian_nack_writer.WriteU16(bitmask); | |
518 number_of_nack_fields++; | |
519 } | |
520 DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields); | |
521 (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields); | |
522 } | |
523 | |
524 void RtcpSender::BuildBye(Packet* packet) const { | |
525 size_t start_size = packet->size(); | |
526 DCHECK_LT(start_size + 8, kMaxIpPacketSize) << "Not enough buffer space"; | |
527 if (start_size + 8 > kMaxIpPacketSize) | |
528 return; | |
529 | |
530 packet->resize(start_size + 8); | |
531 | |
532 base::BigEndianWriter big_endian_writer( | |
533 reinterpret_cast<char*>(&((*packet)[start_size])), 8); | |
534 big_endian_writer.WriteU8(0x80 + 1); | |
535 big_endian_writer.WriteU8(kPacketTypeBye); | |
536 big_endian_writer.WriteU16(1); // Length. | |
537 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
538 } | |
539 | |
540 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, | 270 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, |
541 Packet* packet) const { | 271 Packet* packet) const { |
542 size_t start_size = packet->size(); | 272 size_t start_size = packet->size(); |
543 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; | 273 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; |
544 if (start_size + 20 > kMaxIpPacketSize) | 274 if (start_size + 20 > kMaxIpPacketSize) |
545 return; | 275 return; |
546 | 276 |
547 packet->resize(start_size + 20); | 277 packet->resize(start_size + 20); |
548 | 278 |
549 base::BigEndianWriter big_endian_writer( | 279 base::BigEndianWriter big_endian_writer( |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 << "Not enough buffer space."; | 650 << "Not enough buffer space."; |
921 | 651 |
922 VLOG(3) << "number of frames: " << *number_of_frames; | 652 VLOG(3) << "number of frames: " << *number_of_frames; |
923 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; | 653 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; |
924 VLOG(3) << "rtcp log size: " << *rtcp_log_size; | 654 VLOG(3) << "rtcp log size: " << *rtcp_log_size; |
925 return *number_of_frames > 0; | 655 return *number_of_frames > 0; |
926 } | 656 } |
927 | 657 |
928 } // namespace cast | 658 } // namespace cast |
929 } // namespace media | 659 } // namespace media |
OLD | NEW |