Use RtcpPacket classes for SenderReport/ReceiveReport in RTCPSender
BUG=2450 R=asapersson@webrtc.org Review URL: https://codereview.webrtc.org/1170723002. Cr-Commit-Position: refs/heads/master@{#9483}
This commit is contained in:
@ -810,13 +810,12 @@ bool SenderReport::Create(uint8_t* packet,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SenderReport::WithReportBlock(ReportBlock* block) {
|
||||
assert(block);
|
||||
bool SenderReport::WithReportBlock(const ReportBlock& block) {
|
||||
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
|
||||
LOG(LS_WARNING) << "Max report blocks reached.";
|
||||
return false;
|
||||
}
|
||||
report_blocks_.push_back(block->report_block_);
|
||||
report_blocks_.push_back(block.report_block_);
|
||||
sr_.NumberOfReportBlocks = report_blocks_.size();
|
||||
return true;
|
||||
}
|
||||
@ -834,13 +833,12 @@ bool ReceiverReport::Create(uint8_t* packet,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReceiverReport::WithReportBlock(ReportBlock* block) {
|
||||
assert(block);
|
||||
bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
|
||||
if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
|
||||
LOG(LS_WARNING) << "Max report blocks reached.";
|
||||
return false;
|
||||
}
|
||||
report_blocks_.push_back(block->report_block_);
|
||||
report_blocks_.push_back(block.report_block_);
|
||||
rr_.NumberOfReportBlocks = report_blocks_.size();
|
||||
return true;
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ class SenderReport : public RtcpPacket {
|
||||
void WithOctetCount(uint32_t octet_count) {
|
||||
sr_.SenderOctetCount = octet_count;
|
||||
}
|
||||
bool WithReportBlock(ReportBlock* block);
|
||||
bool WithReportBlock(const ReportBlock& block);
|
||||
|
||||
protected:
|
||||
bool Create(uint8_t* packet,
|
||||
@ -282,7 +282,7 @@ class ReceiverReport : public RtcpPacket {
|
||||
void From(uint32_t ssrc) {
|
||||
rr_.SenderSSRC = ssrc;
|
||||
}
|
||||
bool WithReportBlock(ReportBlock* block);
|
||||
bool WithReportBlock(const ReportBlock& block);
|
||||
|
||||
protected:
|
||||
bool Create(uint8_t* packet,
|
||||
|
@ -71,7 +71,7 @@ TEST(RtcpPacketTest, RrWithOneReportBlock) {
|
||||
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
|
||||
rtc::scoped_ptr<RawPacket> packet(rr.Build());
|
||||
RtcpPacketParser parser;
|
||||
@ -96,8 +96,8 @@ TEST(RtcpPacketTest, RrWithTwoReportBlocks) {
|
||||
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb1));
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb2));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb1));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb2));
|
||||
|
||||
rtc::scoped_ptr<RawPacket> packet(rr.Build());
|
||||
RtcpPacketParser parser;
|
||||
@ -116,10 +116,10 @@ TEST(RtcpPacketTest, RrWithTooManyReportBlocks) {
|
||||
ReportBlock rb;
|
||||
for (int i = 0; i < kMaxReportBlocks; ++i) {
|
||||
rb.To(kRemoteSsrc + i);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
}
|
||||
rb.To(kRemoteSsrc + kMaxReportBlocks);
|
||||
EXPECT_FALSE(rr.WithReportBlock(&rb));
|
||||
EXPECT_FALSE(rr.WithReportBlock(rb));
|
||||
}
|
||||
|
||||
TEST(RtcpPacketTest, Sr) {
|
||||
@ -151,7 +151,7 @@ TEST(RtcpPacketTest, SrWithOneReportBlock) {
|
||||
|
||||
SenderReport sr;
|
||||
sr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(sr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(sr.WithReportBlock(rb));
|
||||
|
||||
rtc::scoped_ptr<RawPacket> packet(sr.Build());
|
||||
RtcpPacketParser parser;
|
||||
@ -170,8 +170,8 @@ TEST(RtcpPacketTest, SrWithTwoReportBlocks) {
|
||||
|
||||
SenderReport sr;
|
||||
sr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(sr.WithReportBlock(&rb1));
|
||||
EXPECT_TRUE(sr.WithReportBlock(&rb2));
|
||||
EXPECT_TRUE(sr.WithReportBlock(rb1));
|
||||
EXPECT_TRUE(sr.WithReportBlock(rb2));
|
||||
|
||||
rtc::scoped_ptr<RawPacket> packet(sr.Build());
|
||||
RtcpPacketParser parser;
|
||||
@ -190,10 +190,10 @@ TEST(RtcpPacketTest, SrWithTooManyReportBlocks) {
|
||||
ReportBlock rb;
|
||||
for (int i = 0; i < kMaxReportBlocks; ++i) {
|
||||
rb.To(kRemoteSsrc + i);
|
||||
EXPECT_TRUE(sr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(sr.WithReportBlock(rb));
|
||||
}
|
||||
rb.To(kRemoteSsrc + kMaxReportBlocks);
|
||||
EXPECT_FALSE(sr.WithReportBlock(&rb));
|
||||
EXPECT_FALSE(sr.WithReportBlock(rb));
|
||||
}
|
||||
|
||||
TEST(RtcpPacketTest, IjNoItem) {
|
||||
@ -567,7 +567,7 @@ TEST(RtcpPacketTest, AppendPacket) {
|
||||
ReportBlock rb;
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
rr.Append(&fir);
|
||||
|
||||
rtc::scoped_ptr<RawPacket> packet(rr.Build());
|
||||
@ -598,7 +598,7 @@ TEST(RtcpPacketTest, AppendPacketWithOwnAppendedPacket) {
|
||||
ReportBlock rb;
|
||||
|
||||
ReceiverReport rr;
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
rr.Append(&fir);
|
||||
|
||||
SenderReport sr;
|
||||
@ -657,7 +657,7 @@ TEST(RtcpPacketTest, BuildWithInputBuffer) {
|
||||
ReportBlock rb;
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
rr.Append(&fir);
|
||||
|
||||
const size_t kRrLength = 8;
|
||||
@ -687,7 +687,7 @@ TEST(RtcpPacketTest, BuildWithTooSmallBuffer) {
|
||||
ReportBlock rb;
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
|
||||
const size_t kRrLength = 8;
|
||||
const size_t kReportBlockLength = 24;
|
||||
@ -708,7 +708,7 @@ TEST(RtcpPacketTest, BuildWithTooSmallBuffer_FragmentedSend) {
|
||||
ReportBlock rb;
|
||||
ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
EXPECT_TRUE(rr.WithReportBlock(&rb));
|
||||
EXPECT_TRUE(rr.WithReportBlock(rb));
|
||||
rr.Append(&fir);
|
||||
|
||||
const size_t kRrLength = 8;
|
||||
|
@ -197,7 +197,7 @@ TEST_F(RtcpReceiverTest, InjectRrPacketWithReportBlockNotToUsIgnored) {
|
||||
rb.To(kSourceSsrc + 1);
|
||||
rtcp::ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
rr.WithReportBlock(&rb);
|
||||
rr.WithReportBlock(rb);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
|
||||
EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
|
||||
@ -220,7 +220,7 @@ TEST_F(RtcpReceiverTest, InjectRrPacketWithOneReportBlock) {
|
||||
rb.To(kSourceSsrc);
|
||||
rtcp::ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
rr.WithReportBlock(&rb);
|
||||
rr.WithReportBlock(rb);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
|
||||
EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
|
||||
@ -255,8 +255,8 @@ TEST_F(RtcpReceiverTest, InjectRrPacketWithTwoReportBlocks) {
|
||||
|
||||
rtcp::ReceiverReport rr1;
|
||||
rr1.From(kSenderSsrc);
|
||||
rr1.WithReportBlock(&rb1);
|
||||
rr1.WithReportBlock(&rb2);
|
||||
rr1.WithReportBlock(rb1);
|
||||
rr1.WithReportBlock(rb2);
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
|
||||
@ -278,8 +278,8 @@ TEST_F(RtcpReceiverTest, InjectRrPacketWithTwoReportBlocks) {
|
||||
|
||||
rtcp::ReceiverReport rr2;
|
||||
rr2.From(kSenderSsrc);
|
||||
rr2.WithReportBlock(&rb3);
|
||||
rr2.WithReportBlock(&rb4);
|
||||
rr2.WithReportBlock(rb3);
|
||||
rr2.WithReportBlock(rb4);
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
|
||||
@ -318,7 +318,7 @@ TEST_F(RtcpReceiverTest, InjectRrPacketsFromTwoRemoteSsrcs) {
|
||||
rb1.WithCumulativeLost(kCumLost[0]);
|
||||
rtcp::ReceiverReport rr1;
|
||||
rr1.From(kSenderSsrc1);
|
||||
rr1.WithReportBlock(&rb1);
|
||||
rr1.WithReportBlock(rb1);
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
|
||||
@ -341,7 +341,7 @@ TEST_F(RtcpReceiverTest, InjectRrPacketsFromTwoRemoteSsrcs) {
|
||||
rb2.WithCumulativeLost(kCumLost[1]);
|
||||
rtcp::ReceiverReport rr2;
|
||||
rr2.From(kSenderSsrc2);
|
||||
rr2.WithReportBlock(&rb2);
|
||||
rr2.WithReportBlock(rb2);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
|
||||
ASSERT_EQ(1u, rtcp_packet_info_.report_blocks.size());
|
||||
@ -374,7 +374,7 @@ TEST_F(RtcpReceiverTest, GetRtt) {
|
||||
rb.To(kSourceSsrc);
|
||||
rtcp::ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
rr.WithReportBlock(&rb);
|
||||
rr.WithReportBlock(rb);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
|
||||
EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
|
||||
@ -484,8 +484,8 @@ TEST_F(RtcpReceiverTest, InjectByePacket_RemovesReportBlocks) {
|
||||
rb2.To(kSourceSsrcs[1]);
|
||||
rtcp::ReceiverReport rr;
|
||||
rr.From(kSenderSsrc);
|
||||
rr.WithReportBlock(&rb1);
|
||||
rr.WithReportBlock(&rb2);
|
||||
rr.WithReportBlock(rb1);
|
||||
rr.WithReportBlock(rb2);
|
||||
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p1(rr.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
|
||||
@ -802,7 +802,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
rb1.WithExtHighestSeqNum(kSequenceNumber);
|
||||
rtcp::ReceiverReport rr1;
|
||||
rr1.From(kSenderSsrc);
|
||||
rr1.WithReportBlock(&rb1);
|
||||
rr1.WithReportBlock(rb1);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
|
||||
system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1);
|
||||
@ -831,7 +831,7 @@ TEST_F(RtcpReceiverTest, ReceiveReportTimeout) {
|
||||
rb2.WithExtHighestSeqNum(kSequenceNumber + 1);
|
||||
rtcp::ReceiverReport rr2;
|
||||
rr2.From(kSenderSsrc);
|
||||
rr2.WithReportBlock(&rb2);
|
||||
rr2.WithReportBlock(rb2);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
|
||||
EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
|
||||
@ -1008,7 +1008,7 @@ TEST_F(RtcpReceiverTest, Callbacks) {
|
||||
|
||||
rtcp::ReceiverReport rr1;
|
||||
rr1.From(kSenderSsrc);
|
||||
rr1.WithReportBlock(&rb1);
|
||||
rr1.WithReportBlock(rb1);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
|
||||
EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss,
|
||||
@ -1026,7 +1026,7 @@ TEST_F(RtcpReceiverTest, Callbacks) {
|
||||
|
||||
rtcp::ReceiverReport rr2;
|
||||
rr2.From(kSenderSsrc);
|
||||
rr2.WithReportBlock(&rb2);
|
||||
rr2.WithReportBlock(rb2);
|
||||
rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
|
||||
EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
|
||||
EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss,
|
||||
|
@ -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);
|
||||
uint32_t rtp_timestamp =
|
||||
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);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
for (auto it : report_blocks_)
|
||||
report.WithReportBlock(it.second);
|
||||
|
||||
// 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();
|
||||
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) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
|
||||
@ -176,24 +177,13 @@ private:
|
||||
|
||||
int32_t SendToNetwork(const uint8_t* dataBuffer, size_t length);
|
||||
|
||||
RTCPSender::BuildResult WriteAllReportBlocksToBuffer(
|
||||
RtcpContext* context,
|
||||
uint8_t* numberOfReportBlocks)
|
||||
int32_t AddReportBlock(const RTCPReportBlock& report_block)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
|
||||
|
||||
void WriteReportBlocksToBuffer(
|
||||
RtcpContext* context,
|
||||
const std::map<uint32_t, RTCPReportBlock*>& report_blocks);
|
||||
|
||||
int32_t AddReportBlock(uint32_t SSRC,
|
||||
std::map<uint32_t, RTCPReportBlock*>* report_blocks,
|
||||
const RTCPReportBlock* receiveBlock);
|
||||
|
||||
bool PrepareReport(const FeedbackState& feedback_state,
|
||||
uint32_t ssrc,
|
||||
StreamStatistician* statistician,
|
||||
RTCPReportBlock* report_block,
|
||||
uint32_t* ntp_secs,
|
||||
uint32_t* ntp_frac);
|
||||
RTCPReportBlock* report_block);
|
||||
|
||||
int PrepareRTCP(const FeedbackState& feedback_state,
|
||||
const std::set<RTCPPacketType>& packetTypes,
|
||||
@ -266,8 +256,9 @@ private:
|
||||
|
||||
ReceiveStatistics* receive_statistics_
|
||||
GUARDED_BY(critical_section_rtcp_sender_);
|
||||
std::map<uint32_t, RTCPReportBlock*> internal_report_blocks_
|
||||
std::map<uint32_t, rtcp::ReportBlock> report_blocks_
|
||||
GUARDED_BY(critical_section_rtcp_sender_);
|
||||
// TODO(sprang): Can we avoid pointers here?
|
||||
std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> csrc_cnames_
|
||||
GUARDED_BY(critical_section_rtcp_sender_);
|
||||
|
||||
@ -338,6 +329,8 @@ private:
|
||||
|
||||
typedef BuildResult (RTCPSender::*Builder)(RtcpContext*);
|
||||
std::map<RTCPPacketType, Builder> builders_;
|
||||
|
||||
class PacketBuiltCallback;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
Reference in New Issue
Block a user