| Index: webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
|
| diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
|
| index a104fec09fc23089c8cd5adaa2e7185271b8834d..11ff4b3b53d19f4c21f9ef51396c4521479f64bf 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
|
| @@ -113,6 +113,20 @@ struct RTCPSender::RtcpContext {
|
| uint32_t position;
|
| };
|
|
|
| +// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
|
| +class RTCPSender::PacketBuiltCallback
|
| + : public rtcp::RtcpPacket::PacketReadyCallback {
|
| + public:
|
| + PacketBuiltCallback(RtcpContext* context) : context_(context) {}
|
| + virtual ~PacketBuiltCallback() {}
|
| + void OnPacketReady(uint8_t* data, size_t length) override {
|
| + context_->position += length;
|
| + }
|
| +
|
| + private:
|
| + RtcpContext* const context_;
|
| +};
|
| +
|
| RTCPSender::RTCPSender(
|
| int32_t id,
|
| bool audio,
|
| @@ -150,6 +164,7 @@ RTCPSender::RTCPSender(
|
| packet_oh_send_(0),
|
|
|
| app_sub_type_(0),
|
| + app_name_(0),
|
| app_data_(nullptr),
|
| app_length_(0),
|
|
|
| @@ -181,9 +196,6 @@ RTCPSender::RTCPSender(
|
| }
|
|
|
| RTCPSender::~RTCPSender() {
|
| - for (auto it : internal_report_blocks_)
|
| - delete it.second;
|
| -
|
| for (auto it : csrc_cnames_)
|
| delete it.second;
|
| }
|
| @@ -465,42 +477,24 @@ bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
|
| return true;
|
| }
|
|
|
| -int32_t RTCPSender::AddReportBlock(
|
| - uint32_t SSRC,
|
| - std::map<uint32_t, RTCPReportBlock*>* report_blocks,
|
| - const RTCPReportBlock* reportBlock) {
|
| - assert(reportBlock);
|
| -
|
| - if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
|
| +int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
|
| + if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
|
| LOG(LS_WARNING) << "Too many report blocks.";
|
| return -1;
|
| }
|
| - std::map<uint32_t, RTCPReportBlock*>::iterator it =
|
| - report_blocks->find(SSRC);
|
| - if (it != report_blocks->end()) {
|
| - delete it->second;
|
| - report_blocks->erase(it);
|
| - }
|
| - RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
|
| - memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
|
| - (*report_blocks)[SSRC] = copyReportBlock;
|
| + rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
|
| + block->To(report_block.remoteSSRC);
|
| + block->WithFractionLost(report_block.fractionLost);
|
| + block->WithCumulativeLost(report_block.cumulativeLost);
|
| + block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
|
| + block->WithJitter(report_block.jitter);
|
| + block->WithLastSr(report_block.lastSR);
|
| + block->WithDelayLastSr(report_block.delaySinceLastSR);
|
| +
|
| return 0;
|
| }
|
|
|
| RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
|
| - // sanity
|
| - if (ctx->position + 52 >= IP_PACKET_SIZE) {
|
| - LOG(LS_WARNING) << "Failed to build Sender Report.";
|
| - return BuildResult::kTruncated;
|
| - }
|
| - uint32_t RTPtime;
|
| -
|
| - uint32_t posNumberOfReportBlocks = ctx->position;
|
| - *ctx->AllocateData(1) = 0x80;
|
| -
|
| - // Sender report
|
| - *ctx->AllocateData(1) = 200;
|
| -
|
| for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
|
| // shift old
|
| last_send_report_[i + 1] = last_send_report_[i];
|
| @@ -514,47 +508,30 @@ RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
|
| // the frame being captured at this moment. We are calculating that
|
| // timestamp as the last frame's timestamp + the time since the last frame
|
| // was captured.
|
| - RTPtime = start_timestamp_ + last_rtp_timestamp_ +
|
| - (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
|
| - (ctx->feedback_state.frequency_hz / 1000);
|
| -
|
| - // Add sender data
|
| - // Save for our length field
|
| - ctx->AllocateData(2);
|
| -
|
| - // Add our own SSRC
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
|
| - // NTP
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), RTPtime);
|
| -
|
| - // sender's packet count
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - ctx->feedback_state.packets_sent);
|
| -
|
| - // sender's octet count
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - ctx->feedback_state.media_bytes_sent);
|
| -
|
| - uint8_t numberOfReportBlocks = 0;
|
| - BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
|
| - switch (result) {
|
| - case BuildResult::kError:
|
| - case BuildResult::kTruncated:
|
| - case BuildResult::kAborted:
|
| - return result;
|
| - case BuildResult::kSuccess:
|
| - break;
|
| - default:
|
| - abort();
|
| + uint32_t rtp_timestamp =
|
| + start_timestamp_ + last_rtp_timestamp_ +
|
| + (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
|
| + (ctx->feedback_state.frequency_hz / 1000);
|
| +
|
| + rtcp::SenderReport report;
|
| + report.From(ssrc_);
|
| + report.WithNtpSec(ctx->ntp_sec);
|
| + report.WithNtpFrac(ctx->ntp_frac);
|
| + report.WithRtpTimestamp(rtp_timestamp);
|
| + report.WithPacketCount(ctx->feedback_state.packets_sent);
|
| + report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
|
| +
|
| + for (auto it : report_blocks_)
|
| + report.WithReportBlock(it.second);
|
| +
|
| + PacketBuiltCallback callback(ctx);
|
| + if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
|
| + ctx->buffer_size - ctx->position,
|
| + &callback)) {
|
| + return BuildResult::kTruncated;
|
| }
|
|
|
| - ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
| -
|
| - uint16_t len = static_cast<uint16_t>((ctx->position / 4) - 1);
|
| - ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[2], len);
|
| -
|
| + report_blocks_.clear();
|
| return BuildResult::kSuccess;
|
| }
|
|
|
| @@ -636,39 +613,19 @@ RTCPSender::BuildResult RTCPSender::BuildSDEC(RtcpContext* ctx) {
|
| }
|
|
|
| RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
|
| - // sanity one block
|
| - if (ctx->position + 32 >= IP_PACKET_SIZE)
|
| + rtcp::ReceiverReport report;
|
| + report.From(ssrc_);
|
| + for (auto it : report_blocks_)
|
| + report.WithReportBlock(it.second);
|
| +
|
| + PacketBuiltCallback callback(ctx);
|
| + if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
|
| + ctx->buffer_size - ctx->position,
|
| + &callback)) {
|
| return BuildResult::kTruncated;
|
| -
|
| - uint32_t posNumberOfReportBlocks = ctx->position;
|
| -
|
| - *ctx->AllocateData(1) = 0x80;
|
| - *ctx->AllocateData(1) = 201;
|
| -
|
| - // Save for our length field
|
| - uint32_t len_pos = ctx->position;
|
| - ctx->AllocateData(2);
|
| -
|
| - // Add our own SSRC
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
|
| -
|
| - uint8_t numberOfReportBlocks = 0;
|
| - BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
|
| - switch (result) {
|
| - case BuildResult::kError:
|
| - case BuildResult::kTruncated:
|
| - case BuildResult::kAborted:
|
| - return result;
|
| - case BuildResult::kSuccess:
|
| - break;
|
| - default:
|
| - abort();
|
| }
|
|
|
| - ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
|
| -
|
| - uint16_t len = uint16_t((ctx->position) / 4 - 1);
|
| - ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[len_pos], len);
|
| + report_blocks_.clear();
|
|
|
| return BuildResult::kSuccess;
|
| }
|
| @@ -1491,9 +1448,9 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
|
| if (!statisticians.empty()) {
|
| for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
|
| RTCPReportBlock report_block;
|
| - if (PrepareReport(feedback_state, it->second, &report_block,
|
| - &context.ntp_sec, &context.ntp_frac)) {
|
| - AddReportBlock(it->first, &internal_report_blocks_, &report_block);
|
| + if (PrepareReport(feedback_state, it->first, it->second,
|
| + &report_block)) {
|
| + AddReportBlock(report_block);
|
| }
|
| }
|
| if (extended_jitter_report_enabled_)
|
| @@ -1539,9 +1496,9 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
|
| }
|
|
|
| bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
|
| + uint32_t ssrc,
|
| StreamStatistician* statistician,
|
| - RTCPReportBlock* report_block,
|
| - uint32_t* ntp_secs, uint32_t* ntp_frac) {
|
| + RTCPReportBlock* report_block) {
|
| // Do we have receive statistics to send?
|
| RtcpStatistics stats;
|
| if (!statistician->GetStatistics(&stats, true))
|
| @@ -1551,18 +1508,22 @@ bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
|
| report_block->extendedHighSeqNum =
|
| stats.extended_max_sequence_number;
|
| report_block->jitter = stats.jitter;
|
| + report_block->remoteSSRC = ssrc;
|
|
|
| - // get our NTP as late as possible to avoid a race
|
| - clock_->CurrentNtp(*ntp_secs, *ntp_frac);
|
| + // TODO(sprang): Do we really need separate time stamps for each report?
|
| + // Get our NTP as late as possible to avoid a race.
|
| + uint32_t ntp_secs;
|
| + uint32_t ntp_frac;
|
| + clock_->CurrentNtp(ntp_secs, ntp_frac);
|
|
|
| - // Delay since last received report
|
| + // Delay since last received report.
|
| uint32_t delaySinceLastReceivedSR = 0;
|
| if ((feedback_state.last_rr_ntp_secs != 0) ||
|
| (feedback_state.last_rr_ntp_frac != 0)) {
|
| - // get the 16 lowest bits of seconds and the 16 higest bits of fractions
|
| - uint32_t now = *ntp_secs & 0x0000FFFF;
|
| + // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
|
| + uint32_t now = ntp_secs & 0x0000FFFF;
|
| now <<= 16;
|
| - now += (*ntp_frac & 0xffff0000) >> 16;
|
| + now += (ntp_frac & 0xffff0000) >> 16;
|
|
|
| uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
|
| receiveTime <<= 16;
|
| @@ -1627,59 +1588,6 @@ bool RTCPSender::RtcpXrReceiverReferenceTime() const {
|
| return xr_send_receiver_reference_time_enabled_;
|
| }
|
|
|
| -// called under critsect critical_section_rtcp_sender_
|
| -RTCPSender::BuildResult RTCPSender::WriteAllReportBlocksToBuffer(
|
| - RtcpContext* ctx,
|
| - uint8_t* numberOfReportBlocks) {
|
| - *numberOfReportBlocks = internal_report_blocks_.size();
|
| - if ((ctx->position + *numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
|
| - LOG(LS_WARNING) << "Can't fit all report blocks.";
|
| - return BuildResult::kError;
|
| - }
|
| - WriteReportBlocksToBuffer(ctx, internal_report_blocks_);
|
| - while (!internal_report_blocks_.empty()) {
|
| - delete internal_report_blocks_.begin()->second;
|
| - internal_report_blocks_.erase(internal_report_blocks_.begin());
|
| - }
|
| - return BuildResult::kSuccess;
|
| -}
|
| -
|
| -void RTCPSender::WriteReportBlocksToBuffer(
|
| - RtcpContext* ctx,
|
| - const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
|
| - std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
|
| - report_blocks.begin();
|
| - for (; it != report_blocks.end(); it++) {
|
| - uint32_t remoteSSRC = it->first;
|
| - RTCPReportBlock* reportBlock = it->second;
|
| - if (reportBlock) {
|
| - // Remote SSRC
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remoteSSRC);
|
| -
|
| - // fraction lost
|
| - *ctx->AllocateData(1) = reportBlock->fractionLost;
|
| -
|
| - // cumulative loss
|
| - ByteWriter<uint32_t, 3>::WriteBigEndian(ctx->AllocateData(3),
|
| - reportBlock->cumulativeLost);
|
| -
|
| - // extended highest seq_no, contain the highest sequence number received
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - reportBlock->extendedHighSeqNum);
|
| -
|
| - // Jitter
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - reportBlock->jitter);
|
| -
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - reportBlock->lastSR);
|
| -
|
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
|
| - reportBlock->delaySinceLastSR);
|
| - }
|
| - }
|
| -}
|
| -
|
| // no callbacks allowed inside this function
|
| int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
|
| uint32_t maxBitrateKbit) {
|
|
|