Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 packets_sent(0), | 67 packets_sent(0), |
| 68 media_bytes_sent(0), | 68 media_bytes_sent(0), |
| 69 send_bitrate(0), | 69 send_bitrate(0), |
| 70 last_rr_ntp_secs(0), | 70 last_rr_ntp_secs(0), |
| 71 last_rr_ntp_frac(0), | 71 last_rr_ntp_frac(0), |
| 72 remote_sr(0), | 72 remote_sr(0), |
| 73 has_last_xr_rr(false), | 73 has_last_xr_rr(false), |
| 74 module(nullptr) { | 74 module(nullptr) { |
| 75 } | 75 } |
| 76 | 76 |
| 77 struct RTCPSender::RtcpContext { | 77 class RTCPSender::RtcpContext : public rtcp::RtcpPacket::PacketReadyCallback { |
| 78 RtcpContext(const FeedbackState& feedback_state, | 78 public: |
| 79 RtcpContext(Transport* transport, | |
| 80 const FeedbackState& feedback_state, | |
| 79 int32_t nack_size, | 81 int32_t nack_size, |
| 80 const uint16_t* nack_list, | 82 const uint16_t* nack_list, |
| 81 bool repeat, | 83 bool repeat, |
| 82 uint64_t picture_id, | 84 uint64_t picture_id, |
| 83 uint8_t* buffer, | 85 uint32_t ntp_sec, |
| 84 uint32_t buffer_size) | 86 uint32_t ntp_frac) |
| 85 : feedback_state(feedback_state), | 87 : transport_(transport), |
| 86 nack_size(nack_size), | 88 buffer_{}, |
|
åsapersson
2015/11/16 14:54:39
needed?
åsapersson
2015/12/01 13:49:20
see comment
sprang_webrtc
2015/12/02 10:33:26
Done.
| |
| 87 nack_list(nack_list), | 89 position_(0), |
| 88 repeat(repeat), | 90 bytes_sent_(0), |
| 89 picture_id(picture_id), | 91 feedback_state_(feedback_state), |
| 90 buffer(buffer), | 92 nack_size_(nack_size), |
| 91 buffer_size(buffer_size), | 93 nack_list_(nack_list), |
| 92 ntp_sec(0), | 94 repeat_(repeat), |
| 93 ntp_frac(0), | 95 picture_id_(picture_id), |
| 94 position(0) {} | 96 ntp_sec_(ntp_sec), |
| 97 ntp_frac_(ntp_frac) {} | |
| 95 | 98 |
| 96 uint8_t* AllocateData(uint32_t bytes) { | 99 virtual ~RtcpContext() {} |
| 97 RTC_DCHECK_LE(position + bytes, buffer_size); | 100 |
| 98 uint8_t* ptr = &buffer[position]; | 101 void OnPacketReady(uint8_t* data, size_t length) override { |
| 99 position += bytes; | 102 if (transport_->SendRtcp(data, length)) |
| 100 return ptr; | 103 bytes_sent_ += length; |
| 104 position_ = 0; | |
| 101 } | 105 } |
| 102 | 106 |
| 103 const FeedbackState& feedback_state; | |
| 104 int32_t nack_size; | |
| 105 const uint16_t* nack_list; | |
| 106 bool repeat; | |
| 107 uint64_t picture_id; | |
| 108 uint8_t* buffer; | |
| 109 uint32_t buffer_size; | |
| 110 uint32_t ntp_sec; | |
| 111 uint32_t ntp_frac; | |
| 112 uint32_t position; | |
| 113 }; | |
| 114 | |
| 115 // TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here. | |
| 116 class RTCPSender::PacketBuiltCallback | |
| 117 : public rtcp::RtcpPacket::PacketReadyCallback { | |
| 118 public: | |
| 119 PacketBuiltCallback(RtcpContext* context) : context_(context) {} | |
| 120 virtual ~PacketBuiltCallback() {} | |
| 121 void OnPacketReady(uint8_t* data, size_t length) override { | |
| 122 context_->position += length; | |
| 123 } | |
| 124 bool BuildPacket(const rtcp::RtcpPacket& packet) { | 107 bool BuildPacket(const rtcp::RtcpPacket& packet) { |
|
åsapersson
2015/10/13 08:50:12
empty.Append(packet); ?
sprang_webrtc
2015/12/02 10:33:26
Done.
| |
| 125 return packet.BuildExternalBuffer( | 108 return packet.CreateAndAddAppended(buffer_, &position_, kBufferSize, this); |
| 126 &context_->buffer[context_->position], | |
| 127 context_->buffer_size - context_->position, this); | |
| 128 } | 109 } |
| 129 | 110 |
| 130 private: | 111 void SendRemaining() { |
| 131 RtcpContext* const context_; | 112 if (position_ > 0) |
| 113 OnPacketReady(buffer_, position_); | |
| 114 } | |
| 115 | |
| 116 static const size_t kBufferSize = IP_PACKET_SIZE - 24; | |
| 117 | |
| 118 Transport* const transport_; | |
| 119 uint8_t buffer_[kBufferSize]; | |
| 120 size_t position_; | |
| 121 uint32_t bytes_sent_; | |
| 122 | |
| 123 const FeedbackState& feedback_state_; | |
| 124 const int32_t nack_size_; | |
| 125 const uint16_t* nack_list_; | |
| 126 const bool repeat_; | |
| 127 const uint64_t picture_id_; | |
| 128 const uint32_t ntp_sec_; | |
| 129 const uint32_t ntp_frac_; | |
| 132 }; | 130 }; |
| 133 | 131 |
| 134 RTCPSender::RTCPSender( | 132 RTCPSender::RTCPSender( |
| 135 bool audio, | 133 bool audio, |
| 136 Clock* clock, | 134 Clock* clock, |
| 137 ReceiveStatistics* receive_statistics, | 135 ReceiveStatistics* receive_statistics, |
| 138 RtcpPacketTypeCounterObserver* packet_type_counter_observer, | 136 RtcpPacketTypeCounterObserver* packet_type_counter_observer, |
| 139 Transport* outgoing_transport) | 137 Transport* outgoing_transport) |
| 140 : audio_(audio), | 138 : audio_(audio), |
| 141 clock_(clock), | 139 clock_(clock), |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 block->WithFractionLost(report_block.fractionLost); | 459 block->WithFractionLost(report_block.fractionLost); |
| 462 block->WithCumulativeLost(report_block.cumulativeLost); | 460 block->WithCumulativeLost(report_block.cumulativeLost); |
| 463 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum); | 461 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum); |
| 464 block->WithJitter(report_block.jitter); | 462 block->WithJitter(report_block.jitter); |
| 465 block->WithLastSr(report_block.lastSR); | 463 block->WithLastSr(report_block.lastSR); |
| 466 block->WithDelayLastSr(report_block.delaySinceLastSR); | 464 block->WithDelayLastSr(report_block.delaySinceLastSR); |
| 467 | 465 |
| 468 return 0; | 466 return 0; |
| 469 } | 467 } |
| 470 | 468 |
| 471 RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) { | 469 bool RTCPSender::BuildSR(RtcpContext* ctx) { |
| 472 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) { | 470 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) { |
| 473 // shift old | 471 // shift old |
| 474 last_send_report_[i + 1] = last_send_report_[i]; | 472 last_send_report_[i + 1] = last_send_report_[i]; |
| 475 last_rtcp_time_[i + 1] = last_rtcp_time_[i]; | 473 last_rtcp_time_[i + 1] = last_rtcp_time_[i]; |
| 476 } | 474 } |
| 477 | 475 |
| 478 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac); | 476 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec_, ctx->ntp_frac_); |
| 479 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16); | 477 last_send_report_[0] = (ctx->ntp_sec_ << 16) + (ctx->ntp_frac_ >> 16); |
| 480 | 478 |
| 481 // The timestamp of this RTCP packet should be estimated as the timestamp of | 479 // The timestamp of this RTCP packet should be estimated as the timestamp of |
| 482 // the frame being captured at this moment. We are calculating that | 480 // the frame being captured at this moment. We are calculating that |
| 483 // timestamp as the last frame's timestamp + the time since the last frame | 481 // timestamp as the last frame's timestamp + the time since the last frame |
| 484 // was captured. | 482 // was captured. |
| 485 uint32_t rtp_timestamp = | 483 uint32_t rtp_timestamp = |
| 486 start_timestamp_ + last_rtp_timestamp_ + | 484 start_timestamp_ + last_rtp_timestamp_ + |
| 487 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * | 485 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * |
| 488 (ctx->feedback_state.frequency_hz / 1000); | 486 (ctx->feedback_state_.frequency_hz / 1000); |
| 489 | 487 |
| 490 rtcp::SenderReport report; | 488 rtcp::SenderReport report; |
| 491 report.From(ssrc_); | 489 report.From(ssrc_); |
| 492 report.WithNtpSec(ctx->ntp_sec); | 490 report.WithNtpSec(ctx->ntp_sec_); |
| 493 report.WithNtpFrac(ctx->ntp_frac); | 491 report.WithNtpFrac(ctx->ntp_frac_); |
| 494 report.WithRtpTimestamp(rtp_timestamp); | 492 report.WithRtpTimestamp(rtp_timestamp); |
| 495 report.WithPacketCount(ctx->feedback_state.packets_sent); | 493 report.WithPacketCount(ctx->feedback_state_.packets_sent); |
| 496 report.WithOctetCount(ctx->feedback_state.media_bytes_sent); | 494 report.WithOctetCount(ctx->feedback_state_.media_bytes_sent); |
| 497 | 495 |
| 498 for (auto it : report_blocks_) | 496 for (auto it : report_blocks_) |
| 499 report.WithReportBlock(it.second); | 497 report.WithReportBlock(it.second); |
| 500 | 498 |
| 501 PacketBuiltCallback callback(ctx); | 499 if (!ctx->BuildPacket(report)) |
|
åsapersson
2015/10/13 08:50:12
Shouldn't the packet be appended here (e.g. append
sprang_webrtc
2015/12/02 10:33:26
Done.
| |
| 502 if (!callback.BuildPacket(report)) | 500 return false; |
| 503 return BuildResult::kTruncated; | |
| 504 | 501 |
| 505 report_blocks_.clear(); | 502 report_blocks_.clear(); |
| 506 return BuildResult::kSuccess; | 503 return true; |
| 507 } | 504 } |
| 508 | 505 |
| 509 RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) { | 506 bool RTCPSender::BuildSDES(RtcpContext* ctx) { |
| 510 size_t length_cname = cname_.length(); | 507 size_t length_cname = cname_.length(); |
| 511 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE)); | 508 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE)); |
| 512 | 509 |
| 513 rtcp::Sdes sdes; | 510 rtcp::Sdes sdes; |
| 514 sdes.WithCName(ssrc_, cname_); | 511 sdes.WithCName(ssrc_, cname_); |
| 515 | 512 |
| 516 for (const auto it : csrc_cnames_) | 513 for (const auto it : csrc_cnames_) |
| 517 sdes.WithCName(it.first, it.second); | 514 sdes.WithCName(it.first, it.second); |
| 518 | 515 |
| 519 PacketBuiltCallback callback(ctx); | 516 return ctx->BuildPacket(sdes); |
| 520 if (!callback.BuildPacket(sdes)) | |
| 521 return BuildResult::kTruncated; | |
| 522 | |
| 523 return BuildResult::kSuccess; | |
| 524 } | 517 } |
| 525 | 518 |
| 526 RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) { | 519 bool RTCPSender::BuildRR(RtcpContext* ctx) { |
| 527 rtcp::ReceiverReport report; | 520 rtcp::ReceiverReport report; |
| 528 report.From(ssrc_); | 521 report.From(ssrc_); |
| 529 for (auto it : report_blocks_) | 522 for (auto it : report_blocks_) |
| 530 report.WithReportBlock(it.second); | 523 report.WithReportBlock(it.second); |
| 531 | 524 |
| 532 PacketBuiltCallback callback(ctx); | 525 if (!ctx->BuildPacket(report)) |
| 533 if (!callback.BuildPacket(report)) | 526 return false; |
| 534 return BuildResult::kTruncated; | |
| 535 | 527 |
| 536 report_blocks_.clear(); | 528 report_blocks_.clear(); |
| 537 | 529 return true; |
| 538 return BuildResult::kSuccess; | |
| 539 } | 530 } |
| 540 | 531 |
| 541 RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) { | 532 bool RTCPSender::BuildPLI(RtcpContext* ctx) { |
| 542 rtcp::Pli pli; | 533 rtcp::Pli pli; |
| 543 pli.From(ssrc_); | 534 pli.From(ssrc_); |
| 544 pli.To(remote_ssrc_); | 535 pli.To(remote_ssrc_); |
| 545 | 536 |
| 546 PacketBuiltCallback callback(ctx); | 537 if (!ctx->BuildPacket(pli)) |
| 547 if (!callback.BuildPacket(pli)) | 538 return false; |
| 548 return BuildResult::kTruncated; | |
| 549 | 539 |
| 550 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 540 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 551 "RTCPSender::PLI"); | 541 "RTCPSender::PLI"); |
| 552 ++packet_type_counter_.pli_packets; | 542 ++packet_type_counter_.pli_packets; |
| 553 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount", | 543 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount", |
| 554 ssrc_, packet_type_counter_.pli_packets); | 544 ssrc_, packet_type_counter_.pli_packets); |
| 555 | 545 |
| 556 return BuildResult::kSuccess; | 546 return true; |
| 557 } | 547 } |
| 558 | 548 |
| 559 RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { | 549 bool RTCPSender::BuildFIR(RtcpContext* ctx) { |
| 560 if (!ctx->repeat) | 550 if (!ctx->repeat_) |
| 561 ++sequence_number_fir_; // Do not increase if repetition. | 551 ++sequence_number_fir_; // Do not increase if repetition. |
| 562 | 552 |
| 563 rtcp::Fir fir; | 553 rtcp::Fir fir; |
| 564 fir.From(ssrc_); | 554 fir.From(ssrc_); |
| 565 fir.To(remote_ssrc_); | 555 fir.To(remote_ssrc_); |
| 566 fir.WithCommandSeqNum(sequence_number_fir_); | 556 fir.WithCommandSeqNum(sequence_number_fir_); |
| 567 | 557 |
| 568 PacketBuiltCallback callback(ctx); | 558 if (!ctx->BuildPacket(fir)) |
| 569 if (!callback.BuildPacket(fir)) | 559 return false; |
| 570 return BuildResult::kTruncated; | |
| 571 | 560 |
| 572 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 561 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 573 "RTCPSender::FIR"); | 562 "RTCPSender::FIR"); |
| 574 ++packet_type_counter_.fir_packets; | 563 ++packet_type_counter_.fir_packets; |
| 575 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount", | 564 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount", |
| 576 ssrc_, packet_type_counter_.fir_packets); | 565 ssrc_, packet_type_counter_.fir_packets); |
| 577 | 566 |
| 578 return BuildResult::kSuccess; | 567 return true; |
| 579 } | 568 } |
| 580 | 569 |
| 581 /* | 570 /* |
| 582 0 1 2 3 | 571 0 1 2 3 |
| 583 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 | 572 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 |
| 584 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 573 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 585 | First | Number | PictureID | | 574 | First | Number | PictureID | |
| 586 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 575 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 587 */ | 576 */ |
| 588 RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) { | 577 bool RTCPSender::BuildSLI(RtcpContext* ctx) { |
| 589 rtcp::Sli sli; | 578 rtcp::Sli sli; |
| 590 sli.From(ssrc_); | 579 sli.From(ssrc_); |
| 591 sli.To(remote_ssrc_); | 580 sli.To(remote_ssrc_); |
| 592 // Crop picture id to 6 least significant bits. | 581 // Crop picture id to 6 least significant bits. |
| 593 sli.WithPictureId(ctx->picture_id & 0x3F); | 582 sli.WithPictureId(ctx->picture_id_ & 0x3F); |
| 594 sli.WithFirstMb(0); | 583 sli.WithFirstMb(0); |
| 595 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now. | 584 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now. |
| 596 | 585 |
| 597 PacketBuiltCallback callback(ctx); | 586 return ctx->BuildPacket(sli); |
| 598 if (!callback.BuildPacket(sli)) | |
| 599 return BuildResult::kTruncated; | |
| 600 | |
| 601 return BuildResult::kSuccess; | |
| 602 } | 587 } |
| 603 | 588 |
| 604 /* | 589 /* |
| 605 0 1 2 3 | 590 0 1 2 3 |
| 606 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 | 591 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 |
| 607 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 592 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 608 | PB |0| Payload Type| Native RPSI bit string | | 593 | PB |0| Payload Type| Native RPSI bit string | |
| 609 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 594 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 610 | defined per codec ... | Padding (0) | | 595 | defined per codec ... | Padding (0) | |
| 611 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 596 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 612 */ | 597 */ |
| 613 /* | 598 /* |
| 614 * Note: not generic made for VP8 | 599 * Note: not generic made for VP8 |
| 615 */ | 600 */ |
| 616 RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) { | 601 bool RTCPSender::BuildRPSI(RtcpContext* ctx) { |
| 617 if (ctx->feedback_state.send_payload_type == 0xFF) | 602 if (ctx->feedback_state_.send_payload_type == 0xFF) |
| 618 return BuildResult::kError; | 603 return false; |
| 619 | 604 |
| 620 rtcp::Rpsi rpsi; | 605 rtcp::Rpsi rpsi; |
| 621 rpsi.From(ssrc_); | 606 rpsi.From(ssrc_); |
| 622 rpsi.To(remote_ssrc_); | 607 rpsi.To(remote_ssrc_); |
| 623 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type); | 608 rpsi.WithPayloadType(ctx->feedback_state_.send_payload_type); |
| 624 rpsi.WithPictureId(ctx->picture_id); | 609 rpsi.WithPictureId(ctx->picture_id_); |
| 625 | 610 |
| 626 PacketBuiltCallback callback(ctx); | 611 return ctx->BuildPacket(rpsi); |
| 627 if (!callback.BuildPacket(rpsi)) | |
| 628 return BuildResult::kTruncated; | |
| 629 | |
| 630 return BuildResult::kSuccess; | |
| 631 } | 612 } |
| 632 | 613 |
| 633 RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) { | 614 bool RTCPSender::BuildREMB(RtcpContext* ctx) { |
| 634 rtcp::Remb remb; | 615 rtcp::Remb remb; |
| 635 remb.From(ssrc_); | 616 remb.From(ssrc_); |
| 636 for (uint32_t ssrc : remb_ssrcs_) | 617 for (uint32_t ssrc : remb_ssrcs_) |
| 637 remb.AppliesTo(ssrc); | 618 remb.AppliesTo(ssrc); |
| 638 remb.WithBitrateBps(remb_bitrate_); | 619 remb.WithBitrateBps(remb_bitrate_); |
| 639 | 620 |
| 640 PacketBuiltCallback callback(ctx); | 621 if (!ctx->BuildPacket(remb)) |
| 641 if (!callback.BuildPacket(remb)) | 622 return false; |
| 642 return BuildResult::kTruncated; | |
| 643 | 623 |
| 644 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 624 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 645 "RTCPSender::REMB"); | 625 "RTCPSender::REMB"); |
| 646 | 626 |
| 647 return BuildResult::kSuccess; | 627 return true; |
| 648 } | 628 } |
| 649 | 629 |
| 650 void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { | 630 void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { |
| 651 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); | 631 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |
| 652 tmmbr_send_ = target_bitrate / 1000; | 632 tmmbr_send_ = target_bitrate / 1000; |
| 653 } | 633 } |
| 654 | 634 |
| 655 RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { | 635 bool RTCPSender::BuildTMMBR(RtcpContext* ctx) { |
| 656 if (ctx->feedback_state.module == NULL) | 636 if (ctx->feedback_state_.module == nullptr) |
| 657 return BuildResult::kError; | 637 return false; |
| 658 // Before sending the TMMBR check the received TMMBN, only an owner is | 638 // Before sending the TMMBR check the received TMMBN, only an owner is |
| 659 // allowed to raise the bitrate: | 639 // allowed to raise the bitrate: |
| 660 // * If the sender is an owner of the TMMBN -> send TMMBR | 640 // * If the sender is an owner of the TMMBN -> send TMMBR |
| 661 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR | 641 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR |
| 662 | 642 |
| 663 // get current bounding set from RTCP receiver | 643 // get current bounding set from RTCP receiver |
| 664 bool tmmbrOwner = false; | 644 bool tmmbrOwner = false; |
| 665 // store in candidateSet, allocates one extra slot | 645 // store in candidateSet, allocates one extra slot |
| 666 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet(); | 646 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet(); |
| 667 | 647 |
| 668 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which | 648 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which |
| 669 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but | 649 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but |
| 670 // since RTCPreceiver is not doing the reverse we should be fine | 650 // since RTCPreceiver is not doing the reverse we should be fine |
| 671 int32_t lengthOfBoundingSet = | 651 int32_t lengthOfBoundingSet = |
| 672 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet); | 652 ctx->feedback_state_.module->BoundingSet(tmmbrOwner, candidateSet); |
| 673 | 653 |
| 674 if (lengthOfBoundingSet > 0) { | 654 if (lengthOfBoundingSet > 0) { |
| 675 for (int32_t i = 0; i < lengthOfBoundingSet; i++) { | 655 for (int32_t i = 0; i < lengthOfBoundingSet; i++) { |
| 676 if (candidateSet->Tmmbr(i) == tmmbr_send_ && | 656 if (candidateSet->Tmmbr(i) == tmmbr_send_ && |
| 677 candidateSet->PacketOH(i) == packet_oh_send_) { | 657 candidateSet->PacketOH(i) == packet_oh_send_) { |
| 678 // do not send the same tuple | 658 // Do not send the same tuple. |
| 679 return BuildResult::kAborted; | 659 return true; |
| 680 } | 660 } |
| 681 } | 661 } |
| 682 if (!tmmbrOwner) { | 662 if (!tmmbrOwner) { |
| 683 // use received bounding set as candidate set | 663 // use received bounding set as candidate set |
| 684 // add current tuple | 664 // add current tuple |
| 685 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_, | 665 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_, |
| 686 ssrc_); | 666 ssrc_); |
| 687 int numCandidates = lengthOfBoundingSet + 1; | 667 int numCandidates = lengthOfBoundingSet + 1; |
| 688 | 668 |
| 689 // find bounding set | 669 // find bounding set |
| 690 TMMBRSet* boundingSet = NULL; | 670 TMMBRSet* boundingSet = nullptr; |
| 691 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet); | 671 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet); |
| 692 if (numBoundingSet > 0 || numBoundingSet <= numCandidates) | 672 if (numBoundingSet > 0 || numBoundingSet <= numCandidates) |
| 693 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet); | 673 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet); |
| 694 if (!tmmbrOwner) { | 674 if (!tmmbrOwner) { |
| 695 // did not enter bounding set, no meaning to send this request | 675 // Did not enter bounding set, no meaning to send this request. |
| 696 return BuildResult::kAborted; | 676 return true; |
| 697 } | 677 } |
| 698 } | 678 } |
| 699 } | 679 } |
| 700 | 680 |
| 701 if (tmmbr_send_) { | 681 if (tmmbr_send_) { |
| 702 rtcp::Tmmbr tmmbr; | 682 rtcp::Tmmbr tmmbr; |
| 703 tmmbr.From(ssrc_); | 683 tmmbr.From(ssrc_); |
| 704 tmmbr.To(remote_ssrc_); | 684 tmmbr.To(remote_ssrc_); |
| 705 tmmbr.WithBitrateKbps(tmmbr_send_); | 685 tmmbr.WithBitrateKbps(tmmbr_send_); |
| 706 tmmbr.WithOverhead(packet_oh_send_); | 686 tmmbr.WithOverhead(packet_oh_send_); |
| 707 | 687 |
| 708 PacketBuiltCallback callback(ctx); | 688 return ctx->BuildPacket(tmmbr); |
| 709 if (!callback.BuildPacket(tmmbr)) | |
| 710 return BuildResult::kTruncated; | |
| 711 } | 689 } |
| 712 return BuildResult::kSuccess; | 690 return true; |
| 713 } | 691 } |
| 714 | 692 |
| 715 RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) { | 693 bool RTCPSender::BuildTMMBN(RtcpContext* ctx) { |
| 716 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend(); | 694 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend(); |
| 717 if (boundingSet == NULL) | 695 if (boundingSet == nullptr) |
| 718 return BuildResult::kError; | 696 return false; |
| 719 | 697 |
| 720 rtcp::Tmmbn tmmbn; | 698 rtcp::Tmmbn tmmbn; |
| 721 tmmbn.From(ssrc_); | 699 tmmbn.From(ssrc_); |
| 722 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) { | 700 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) { |
| 723 if (boundingSet->Tmmbr(i) > 0) { | 701 if (boundingSet->Tmmbr(i) > 0) { |
| 724 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), | 702 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), |
| 725 boundingSet->PacketOH(i)); | 703 boundingSet->PacketOH(i)); |
| 726 } | 704 } |
| 727 } | 705 } |
| 728 | 706 |
| 729 PacketBuiltCallback callback(ctx); | 707 return ctx->BuildPacket(tmmbn); |
| 730 if (!callback.BuildPacket(tmmbn)) | |
| 731 return BuildResult::kTruncated; | |
| 732 | |
| 733 return BuildResult::kSuccess; | |
| 734 } | 708 } |
| 735 | 709 |
| 736 RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) { | 710 bool RTCPSender::BuildAPP(RtcpContext* ctx) { |
| 737 rtcp::App app; | 711 rtcp::App app; |
| 738 app.From(ssrc_); | 712 app.From(ssrc_); |
| 739 app.WithSubType(app_sub_type_); | 713 app.WithSubType(app_sub_type_); |
| 740 app.WithName(app_name_); | 714 app.WithName(app_name_); |
| 741 app.WithData(app_data_.get(), app_length_); | 715 app.WithData(app_data_.get(), app_length_); |
| 742 | 716 |
| 743 PacketBuiltCallback callback(ctx); | 717 return ctx->BuildPacket(app); |
| 744 if (!callback.BuildPacket(app)) | |
| 745 return BuildResult::kTruncated; | |
| 746 | |
| 747 return BuildResult::kSuccess; | |
| 748 } | 718 } |
| 749 | 719 |
| 750 RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) { | 720 bool RTCPSender::BuildNACK(RtcpContext* ctx) { |
| 751 // sanity | 721 rtcp::Nack nack; |
| 752 if (ctx->position + 16 >= IP_PACKET_SIZE) { | 722 nack.From(ssrc_); |
| 753 LOG(LS_WARNING) << "Failed to build NACK."; | 723 nack.To(remote_ssrc_); |
| 754 return BuildResult::kTruncated; | 724 nack.WithList(ctx->nack_list_, ctx->nack_size_); |
| 755 } | |
| 756 | 725 |
| 757 // int size, uint16_t* nack_list | 726 if (!ctx->BuildPacket(nack)) |
| 758 // add nack list | 727 return false; |
| 759 uint8_t FMT = 1; | |
| 760 *ctx->AllocateData(1) = 0x80 + FMT; | |
| 761 *ctx->AllocateData(1) = 205; | |
| 762 | |
| 763 *ctx->AllocateData(1) = 0; | |
| 764 int nack_size_pos_ = ctx->position; | |
| 765 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default | |
| 766 | |
| 767 // Add our own SSRC | |
| 768 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_); | |
| 769 | |
| 770 // Add the remote SSRC | |
| 771 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_); | |
| 772 | |
| 773 // Build NACK bitmasks and write them to the RTCP message. | |
| 774 // The nack list should be sorted and not contain duplicates if one | |
| 775 // wants to build the smallest rtcp nack packet. | |
| 776 int numOfNackFields = 0; | |
| 777 int maxNackFields = | |
| 778 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4); | |
| 779 int i = 0; | |
| 780 while (i < ctx->nack_size && numOfNackFields < maxNackFields) { | |
| 781 uint16_t nack = ctx->nack_list[i++]; | |
| 782 uint16_t bitmask = 0; | |
| 783 while (i < ctx->nack_size) { | |
| 784 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1; | |
| 785 if (shift >= 0 && shift <= 15) { | |
| 786 bitmask |= (1 << shift); | |
| 787 ++i; | |
| 788 } else { | |
| 789 break; | |
| 790 } | |
| 791 } | |
| 792 // Write the sequence number and the bitmask to the packet. | |
| 793 assert(ctx->position + 4 < IP_PACKET_SIZE); | |
| 794 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack); | |
| 795 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask); | |
| 796 numOfNackFields++; | |
| 797 } | |
| 798 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields); | |
| 799 | |
| 800 if (i != ctx->nack_size) | |
| 801 LOG(LS_WARNING) << "Nack list too large for one packet."; | |
| 802 | 728 |
| 803 // Report stats. | 729 // Report stats. |
| 804 NACKStringBuilder stringBuilder; | 730 NACKStringBuilder stringBuilder; |
| 805 for (int idx = 0; idx < i; ++idx) { | 731 for (int idx = 0; idx < ctx->nack_size_; ++idx) { |
| 806 stringBuilder.PushNACK(ctx->nack_list[idx]); | 732 stringBuilder.PushNACK(ctx->nack_list_[idx]); |
| 807 nack_stats_.ReportRequest(ctx->nack_list[idx]); | 733 nack_stats_.ReportRequest(ctx->nack_list_[idx]); |
| 808 } | 734 } |
| 809 packet_type_counter_.nack_requests = nack_stats_.requests(); | 735 packet_type_counter_.nack_requests = nack_stats_.requests(); |
| 810 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests(); | 736 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests(); |
| 811 | 737 |
| 812 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 738 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 813 "RTCPSender::NACK", "nacks", | 739 "RTCPSender::NACK", "nacks", |
| 814 TRACE_STR_COPY(stringBuilder.GetResult().c_str())); | 740 TRACE_STR_COPY(stringBuilder.GetResult().c_str())); |
| 815 ++packet_type_counter_.nack_packets; | 741 ++packet_type_counter_.nack_packets; |
| 816 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount", | 742 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount", |
| 817 ssrc_, packet_type_counter_.nack_packets); | 743 ssrc_, packet_type_counter_.nack_packets); |
| 818 | 744 |
| 819 return BuildResult::kSuccess; | 745 return true; |
| 820 } | 746 } |
| 821 | 747 |
| 822 RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) { | 748 bool RTCPSender::BuildBYE(RtcpContext* ctx) { |
| 823 rtcp::Bye bye; | 749 rtcp::Bye bye; |
| 824 bye.From(ssrc_); | 750 bye.From(ssrc_); |
| 825 for (uint32_t csrc : csrcs_) | 751 for (uint32_t csrc : csrcs_) |
| 826 bye.WithCsrc(csrc); | 752 bye.WithCsrc(csrc); |
| 827 | 753 |
| 828 PacketBuiltCallback callback(ctx); | 754 return ctx->BuildPacket(bye); |
| 829 if (!callback.BuildPacket(bye)) | |
| 830 return BuildResult::kTruncated; | |
| 831 | |
| 832 return BuildResult::kSuccess; | |
| 833 } | 755 } |
| 834 | 756 |
| 835 RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime( | 757 bool RTCPSender::BuildReceiverReferenceTime(RtcpContext* ctx) { |
| 836 RtcpContext* ctx) { | |
| 837 | |
| 838 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) | 758 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) |
| 839 last_xr_rr_.erase(last_xr_rr_.begin()); | 759 last_xr_rr_.erase(last_xr_rr_.begin()); |
| 840 last_xr_rr_.insert(std::pair<uint32_t, int64_t>( | 760 last_xr_rr_.insert(std::pair<uint32_t, int64_t>( |
| 841 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac), | 761 RTCPUtility::MidNtp(ctx->ntp_sec_, ctx->ntp_frac_), |
| 842 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac))); | 762 Clock::NtpToMs(ctx->ntp_sec_, ctx->ntp_frac_))); |
| 843 | 763 |
| 844 rtcp::Xr xr; | 764 rtcp::Xr xr; |
| 845 xr.From(ssrc_); | 765 xr.From(ssrc_); |
| 846 | 766 |
| 847 rtcp::Rrtr rrtr; | 767 rtcp::Rrtr rrtr; |
| 848 rrtr.WithNtpSec(ctx->ntp_sec); | 768 rrtr.WithNtpSec(ctx->ntp_sec_); |
| 849 rrtr.WithNtpFrac(ctx->ntp_frac); | 769 rrtr.WithNtpFrac(ctx->ntp_frac_); |
| 850 | 770 |
| 851 xr.WithRrtr(&rrtr); | 771 xr.WithRrtr(&rrtr); |
| 852 | 772 |
| 853 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP? | 773 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP? |
| 854 | 774 |
| 855 PacketBuiltCallback callback(ctx); | 775 return ctx->BuildPacket(xr); |
| 856 if (!callback.BuildPacket(xr)) | |
| 857 return BuildResult::kTruncated; | |
| 858 | |
| 859 return BuildResult::kSuccess; | |
| 860 } | 776 } |
| 861 | 777 |
| 862 RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) { | 778 bool RTCPSender::BuildDlrr(RtcpContext* ctx) { |
| 863 rtcp::Xr xr; | 779 rtcp::Xr xr; |
| 864 xr.From(ssrc_); | 780 xr.From(ssrc_); |
| 865 | 781 |
| 866 rtcp::Dlrr dlrr; | 782 rtcp::Dlrr dlrr; |
| 867 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr; | 783 const RtcpReceiveTimeInfo& info = ctx->feedback_state_.last_xr_rr; |
| 868 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR); | 784 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR); |
| 869 | 785 |
| 870 xr.WithDlrr(&dlrr); | 786 xr.WithDlrr(&dlrr); |
| 871 | 787 |
| 872 PacketBuiltCallback callback(ctx); | 788 return ctx->BuildPacket(xr); |
| 873 if (!callback.BuildPacket(xr)) | |
| 874 return BuildResult::kTruncated; | |
| 875 | |
| 876 return BuildResult::kSuccess; | |
| 877 } | 789 } |
| 878 | 790 |
| 879 // TODO(sprang): Add a unit test for this, or remove if the code isn't used. | 791 // TODO(sprang): Add a unit test for this, or remove if the code isn't used. |
| 880 RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) { | 792 bool RTCPSender::BuildVoIPMetric(RtcpContext* ctx) { |
| 881 rtcp::Xr xr; | 793 rtcp::Xr xr; |
| 882 xr.From(ssrc_); | 794 xr.From(ssrc_); |
| 883 | 795 |
| 884 rtcp::VoipMetric voip; | 796 rtcp::VoipMetric voip; |
| 885 voip.To(remote_ssrc_); | 797 voip.To(remote_ssrc_); |
| 886 voip.LossRate(xr_voip_metric_.lossRate); | 798 voip.LossRate(xr_voip_metric_.lossRate); |
| 887 voip.DiscardRate(xr_voip_metric_.discardRate); | 799 voip.DiscardRate(xr_voip_metric_.discardRate); |
| 888 voip.BurstDensity(xr_voip_metric_.burstDensity); | 800 voip.BurstDensity(xr_voip_metric_.burstDensity); |
| 889 voip.GapDensity(xr_voip_metric_.gapDensity); | 801 voip.GapDensity(xr_voip_metric_.gapDensity); |
| 890 voip.BurstDuration(xr_voip_metric_.burstDuration); | 802 voip.BurstDuration(xr_voip_metric_.burstDuration); |
| 891 voip.GapDuration(xr_voip_metric_.gapDuration); | 803 voip.GapDuration(xr_voip_metric_.gapDuration); |
| 892 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay); | 804 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay); |
| 893 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay); | 805 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay); |
| 894 voip.SignalLevel(xr_voip_metric_.signalLevel); | 806 voip.SignalLevel(xr_voip_metric_.signalLevel); |
| 895 voip.NoiseLevel(xr_voip_metric_.noiseLevel); | 807 voip.NoiseLevel(xr_voip_metric_.noiseLevel); |
| 896 voip.Rerl(xr_voip_metric_.RERL); | 808 voip.Rerl(xr_voip_metric_.RERL); |
| 897 voip.Gmin(xr_voip_metric_.Gmin); | 809 voip.Gmin(xr_voip_metric_.Gmin); |
| 898 voip.Rfactor(xr_voip_metric_.Rfactor); | 810 voip.Rfactor(xr_voip_metric_.Rfactor); |
| 899 voip.ExtRfactor(xr_voip_metric_.extRfactor); | 811 voip.ExtRfactor(xr_voip_metric_.extRfactor); |
| 900 voip.MosLq(xr_voip_metric_.MOSLQ); | 812 voip.MosLq(xr_voip_metric_.MOSLQ); |
| 901 voip.MosCq(xr_voip_metric_.MOSCQ); | 813 voip.MosCq(xr_voip_metric_.MOSCQ); |
| 902 voip.RxConfig(xr_voip_metric_.RXconfig); | 814 voip.RxConfig(xr_voip_metric_.RXconfig); |
| 903 voip.JbNominal(xr_voip_metric_.JBnominal); | 815 voip.JbNominal(xr_voip_metric_.JBnominal); |
| 904 voip.JbMax(xr_voip_metric_.JBmax); | 816 voip.JbMax(xr_voip_metric_.JBmax); |
| 905 voip.JbAbsMax(xr_voip_metric_.JBabsMax); | 817 voip.JbAbsMax(xr_voip_metric_.JBabsMax); |
| 906 | 818 |
| 907 xr.WithVoipMetric(&voip); | 819 xr.WithVoipMetric(&voip); |
| 908 | 820 |
| 909 PacketBuiltCallback callback(ctx); | 821 return ctx->BuildPacket(xr); |
| 910 if (!callback.BuildPacket(xr)) | |
| 911 return BuildResult::kTruncated; | |
| 912 | |
| 913 return BuildResult::kSuccess; | |
| 914 } | 822 } |
| 915 | 823 |
| 916 int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, | 824 int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, |
| 917 RTCPPacketType packetType, | 825 RTCPPacketType packetType, |
| 918 int32_t nack_size, | 826 int32_t nack_size, |
| 919 const uint16_t* nack_list, | 827 const uint16_t* nack_list, |
| 920 bool repeat, | 828 bool repeat, |
| 921 uint64_t pictureID) { | 829 uint64_t pictureID) { |
| 922 return SendCompoundRTCP( | 830 return SendCompoundRTCP( |
| 923 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1), | 831 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1), |
| 924 nack_size, nack_list, repeat, pictureID); | 832 nack_size, nack_list, repeat, pictureID); |
| 925 } | 833 } |
| 926 | 834 |
| 927 int32_t RTCPSender::SendCompoundRTCP( | 835 int32_t RTCPSender::SendCompoundRTCP( |
| 928 const FeedbackState& feedback_state, | 836 const FeedbackState& feedback_state, |
| 929 const std::set<RTCPPacketType>& packetTypes, | 837 const std::set<RTCPPacketType>& packet_types, |
| 930 int32_t nack_size, | 838 int32_t nack_size, |
| 931 const uint16_t* nack_list, | 839 const uint16_t* nack_list, |
| 932 bool repeat, | 840 bool repeat, |
| 933 uint64_t pictureID) { | 841 uint64_t pictureID) { |
| 934 { | 842 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |
| 935 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); | 843 |
| 936 if (method_ == kRtcpOff) { | 844 if (method_ == kRtcpOff) { |
| 937 LOG(LS_WARNING) << "Can't send rtcp if it is disabled."; | 845 LOG(LS_WARNING) << "Can't send rtcp if it is disabled."; |
| 938 return -1; | 846 return -1; |
| 847 } | |
| 848 | |
| 849 // We need to send our NTP even if we haven't received any reports. | |
| 850 uint32_t ntp_sec; | |
| 851 uint32_t ntp_frac; | |
| 852 clock_->CurrentNtp(ntp_sec, ntp_frac); | |
| 853 RtcpContext context(transport_, feedback_state, nack_size, nack_list, repeat, | |
| 854 pictureID, ntp_sec, ntp_frac); | |
| 855 | |
| 856 PrepareReport(packet_types, feedback_state); | |
| 857 | |
| 858 auto it = report_flags_.begin(); | |
| 859 while (it != report_flags_.end()) { | |
| 860 auto builder = builders_.find(it->type); | |
| 861 RTC_DCHECK(builder != builders_.end()); | |
| 862 if (it->is_volatile) { | |
| 863 report_flags_.erase(it++); | |
| 864 } else { | |
| 865 ++it; | |
| 939 } | 866 } |
| 867 | |
| 868 if (!(this->*(builder->second))(&context)) | |
| 869 return false; | |
|
åsapersson
2015/11/16 14:54:39
return -1;
åsapersson
2015/12/01 13:49:20
see comment
sprang_webrtc
2015/12/02 10:33:26
Done.
| |
| 940 } | 870 } |
| 941 uint8_t rtcp_buffer[IP_PACKET_SIZE]; | |
| 942 int rtcp_length = | |
| 943 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat, | |
| 944 pictureID, rtcp_buffer, IP_PACKET_SIZE); | |
| 945 | 871 |
|
åsapersson
2015/11/16 14:54:39
lock needed when sending?
sprang_webrtc
2015/12/01 10:23:06
No, the lock was needed before to protect the poin
åsapersson
2015/12/01 13:49:20
Isn't the lock now held when sending (while it was
sprang_webrtc
2015/12/02 10:33:26
Changed so we collect RtcpPacket instances first,
| |
| 946 // Sanity don't send empty packets. | 872 context.SendRemaining(); |
| 947 if (rtcp_length <= 0) | |
| 948 return -1; | |
| 949 | 873 |
| 950 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length)); | 874 if (packet_type_counter_observer_ != nullptr) { |
| 875 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( | |
| 876 remote_ssrc_, packet_type_counter_); | |
| 877 } | |
| 878 | |
| 879 RTC_DCHECK(AllVolatileFlagsConsumed()); | |
| 880 | |
| 881 return context.bytes_sent_ > 0 ? 0 : -1; | |
|
åsapersson
2015/10/13 08:50:12
And build the packet here?
something like
contex
sprang_webrtc
2015/11/03 15:40:32
That was my initial thought, but it has some drawb
| |
| 951 } | 882 } |
| 952 | 883 |
| 953 int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, | 884 void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes, |
| 954 const std::set<RTCPPacketType>& packetTypes, | 885 const FeedbackState& feedback_state) { |
| 955 int32_t nack_size, | |
| 956 const uint16_t* nack_list, | |
| 957 bool repeat, | |
| 958 uint64_t pictureID, | |
| 959 uint8_t* rtcp_buffer, | |
| 960 int buffer_size) { | |
| 961 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); | |
| 962 | |
| 963 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID, | |
| 964 rtcp_buffer, buffer_size); | |
| 965 | |
| 966 // Add all flags as volatile. Non volatile entries will not be overwritten | 886 // Add all flags as volatile. Non volatile entries will not be overwritten |
| 967 // and all new volatile flags added will be consumed by the end of this call. | 887 // and all new volatile flags added will be consumed by the end of this call. |
| 968 SetFlags(packetTypes, true); | 888 SetFlags(packetTypes, true); |
| 969 | 889 |
| 970 if (packet_type_counter_.first_packet_time_ms == -1) | 890 if (packet_type_counter_.first_packet_time_ms == -1) |
| 971 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds(); | 891 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds(); |
| 972 | 892 |
| 973 bool generate_report; | 893 bool generate_report; |
| 974 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) { | 894 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) { |
| 975 // Report type already explicitly set, don't automatically populate. | 895 // Report type already explicitly set, don't automatically populate. |
| 976 generate_report = true; | 896 generate_report = true; |
| 977 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false); | 897 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false); |
| 978 } else { | 898 } else { |
| 979 generate_report = | 899 generate_report = |
| 980 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) || | 900 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) || |
| 981 method_ == kRtcpCompound; | 901 method_ == kRtcpCompound; |
| 982 if (generate_report) | 902 if (generate_report) |
| 983 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true); | 903 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true); |
| 984 } | 904 } |
| 985 | 905 |
| 986 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty())) | 906 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty())) |
| 987 SetFlag(kRtcpSdes, true); | 907 SetFlag(kRtcpSdes, true); |
| 988 | 908 |
| 989 // We need to send our NTP even if we haven't received any reports. | |
| 990 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac); | |
| 991 | |
| 992 if (generate_report) { | 909 if (generate_report) { |
| 993 if (!sending_ && xr_send_receiver_reference_time_enabled_) | 910 if (!sending_ && xr_send_receiver_reference_time_enabled_) |
| 994 SetFlag(kRtcpXrReceiverReferenceTime, true); | 911 SetFlag(kRtcpXrReceiverReferenceTime, true); |
| 995 if (feedback_state.has_last_xr_rr) | 912 if (feedback_state.has_last_xr_rr) |
| 996 SetFlag(kRtcpXrDlrrReportBlock, true); | 913 SetFlag(kRtcpXrDlrrReportBlock, true); |
| 997 | 914 |
| 998 // generate next time to send an RTCP report | 915 // generate next time to send an RTCP report |
| 999 // seeded from RTP constructor | 916 // seeded from RTP constructor |
| 1000 int32_t random = rand() % 1000; | 917 int32_t random = rand() % 1000; |
| 1001 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS; | 918 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1015 minIntervalMs = RTCP_INTERVAL_VIDEO_MS; | 932 minIntervalMs = RTCP_INTERVAL_VIDEO_MS; |
| 1016 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000); | 933 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000); |
| 1017 } | 934 } |
| 1018 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext; | 935 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext; |
| 1019 | 936 |
| 1020 StatisticianMap statisticians = | 937 StatisticianMap statisticians = |
| 1021 receive_statistics_->GetActiveStatisticians(); | 938 receive_statistics_->GetActiveStatisticians(); |
| 1022 if (!statisticians.empty()) { | 939 if (!statisticians.empty()) { |
| 1023 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) { | 940 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) { |
| 1024 RTCPReportBlock report_block; | 941 RTCPReportBlock report_block; |
| 1025 if (PrepareReport(feedback_state, it->first, it->second, | 942 if (PrepareReportBlock(feedback_state, it->first, it->second, |
| 1026 &report_block)) { | 943 &report_block)) { |
| 1027 AddReportBlock(report_block); | 944 AddReportBlock(report_block); |
| 1028 } | 945 } |
| 1029 } | 946 } |
| 1030 } | 947 } |
| 1031 } | 948 } |
| 1032 | |
| 1033 auto it = report_flags_.begin(); | |
| 1034 while (it != report_flags_.end()) { | |
| 1035 auto builder = builders_.find(it->type); | |
| 1036 RTC_DCHECK(builder != builders_.end()); | |
| 1037 if (it->is_volatile) { | |
| 1038 report_flags_.erase(it++); | |
| 1039 } else { | |
| 1040 ++it; | |
| 1041 } | |
| 1042 | |
| 1043 uint32_t start_position = context.position; | |
| 1044 BuildResult result = (this->*(builder->second))(&context); | |
| 1045 switch (result) { | |
| 1046 case BuildResult::kError: | |
| 1047 return -1; | |
| 1048 case BuildResult::kTruncated: | |
| 1049 return context.position; | |
| 1050 case BuildResult::kAborted: | |
| 1051 context.position = start_position; | |
| 1052 FALLTHROUGH(); | |
| 1053 case BuildResult::kSuccess: | |
| 1054 continue; | |
| 1055 default: | |
| 1056 abort(); | |
| 1057 } | |
| 1058 } | |
| 1059 | |
| 1060 if (packet_type_counter_observer_ != NULL) { | |
| 1061 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( | |
| 1062 remote_ssrc_, packet_type_counter_); | |
| 1063 } | |
| 1064 | |
| 1065 RTC_DCHECK(AllVolatileFlagsConsumed()); | |
| 1066 | |
| 1067 return context.position; | |
| 1068 } | 949 } |
| 1069 | 950 |
| 1070 bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, | 951 bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state, |
| 1071 uint32_t ssrc, | 952 uint32_t ssrc, |
| 1072 StreamStatistician* statistician, | 953 StreamStatistician* statistician, |
| 1073 RTCPReportBlock* report_block) { | 954 RTCPReportBlock* report_block) { |
| 1074 // Do we have receive statistics to send? | 955 // Do we have receive statistics to send? |
| 1075 RtcpStatistics stats; | 956 RtcpStatistics stats; |
| 1076 if (!statistician->GetStatistics(&stats, true)) | 957 if (!statistician->GetStatistics(&stats, true)) |
| 1077 return false; | 958 return false; |
| 1078 report_block->fractionLost = stats.fraction_lost; | 959 report_block->fractionLost = stats.fraction_lost; |
| 1079 report_block->cumulativeLost = stats.cumulative_lost; | 960 report_block->cumulativeLost = stats.cumulative_lost; |
| 1080 report_block->extendedHighSeqNum = | 961 report_block->extendedHighSeqNum = |
| 1081 stats.extended_max_sequence_number; | 962 stats.extended_max_sequence_number; |
| 1082 report_block->jitter = stats.jitter; | 963 report_block->jitter = stats.jitter; |
| 1083 report_block->remoteSSRC = ssrc; | 964 report_block->remoteSSRC = ssrc; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1101 receiveTime <<= 16; | 982 receiveTime <<= 16; |
| 1102 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16; | 983 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16; |
| 1103 | 984 |
| 1104 delaySinceLastReceivedSR = now-receiveTime; | 985 delaySinceLastReceivedSR = now-receiveTime; |
| 1105 } | 986 } |
| 1106 report_block->delaySinceLastSR = delaySinceLastReceivedSR; | 987 report_block->delaySinceLastSR = delaySinceLastReceivedSR; |
| 1107 report_block->lastSR = feedback_state.remote_sr; | 988 report_block->lastSR = feedback_state.remote_sr; |
| 1108 return true; | 989 return true; |
| 1109 } | 990 } |
| 1110 | 991 |
| 1111 int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) { | |
| 1112 if (transport_->SendRtcp(dataBuffer, length)) | |
| 1113 return 0; | |
| 1114 return -1; | |
| 1115 } | |
| 1116 | |
| 1117 void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) { | 992 void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) { |
| 1118 assert(csrcs.size() <= kRtpCsrcSize); | 993 assert(csrcs.size() <= kRtpCsrcSize); |
| 1119 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); | 994 CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |
| 1120 csrcs_ = csrcs; | 995 csrcs_ = csrcs; |
| 1121 } | 996 } |
| 1122 | 997 |
| 1123 int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType, | 998 int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType, |
| 1124 uint32_t name, | 999 uint32_t name, |
| 1125 const uint8_t* data, | 1000 const uint8_t* data, |
| 1126 uint16_t length) { | 1001 uint16_t length) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1214 Transport* const transport_; | 1089 Transport* const transport_; |
| 1215 bool send_failure_; | 1090 bool send_failure_; |
| 1216 } sender(transport_); | 1091 } sender(transport_); |
| 1217 | 1092 |
| 1218 uint8_t buffer[IP_PACKET_SIZE]; | 1093 uint8_t buffer[IP_PACKET_SIZE]; |
| 1219 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) && | 1094 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) && |
| 1220 !sender.send_failure_; | 1095 !sender.send_failure_; |
| 1221 } | 1096 } |
| 1222 | 1097 |
| 1223 } // namespace webrtc | 1098 } // namespace webrtc |
| OLD | NEW |