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) { |