Wire up RTCP XR target bitrate in rtp/rtcp module

This is breakout of the rtcp parts of
https://codereview.webrtc.org/2531383002/

BUG=webrtc:6301

Review-Url: https://codereview.webrtc.org/2546713002
Cr-Commit-Position: refs/heads/master@{#15358}
This commit is contained in:
sprang
2016-12-01 05:18:09 -08:00
committed by Commit bot
parent b57e0f6836
commit 5e38c967e0
8 changed files with 122 additions and 56 deletions

View File

@ -424,6 +424,8 @@ class RtpRtcp : public Module {
// BWE feedback packets.
virtual bool SendFeedbackPacket(const rtcp::TransportFeedback& packet) = 0;
virtual void SetVideoBitrateAllocation(const BitrateAllocation& bitrate) = 0;
// **************************************************************************
// Audio
// **************************************************************************

View File

@ -102,6 +102,7 @@ enum RTCPPacketType : uint32_t {
kRtcpXrReceiverReferenceTime = 0x40000,
kRtcpXrDlrrReportBlock = 0x80000,
kRtcpTransportFeedback = 0x100000,
kRtcpXrTargetBitrate = 0x200000
};
enum KeyFrameRequestMethod { kKeyFrameReqPliRtcp, kKeyFrameReqFirRtcp };

View File

@ -204,6 +204,7 @@ class MockRtpRtcp : public RtpRtcp {
void(StreamDataCountersCallback*));
MOCK_CONST_METHOD0(GetSendChannelRtpStatisticsCallback,
StreamDataCountersCallback*(void));
MOCK_METHOD1(SetVideoBitrateAllocation, void(const BitrateAllocation&));
// Members.
unsigned int remote_ssrc_;
};

View File

@ -42,6 +42,12 @@
namespace webrtc {
namespace {
const uint32_t kRtcpAnyExtendedReports =
kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
kRtcpXrTargetBitrate;
} // namespace
NACKStringBuilder::NACKStringBuilder()
: stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
@ -197,10 +203,7 @@ RTCPSender::RTCPSender(
builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
builders_[kRtcpNack] = &RTCPSender::BuildNACK;
builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
builders_[kRtcpXrReceiverReferenceTime] =
&RTCPSender::BuildReceiverReferenceTime;
builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
}
RTCPSender::~RTCPSender() {}
@ -692,44 +695,47 @@ std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
return std::unique_ptr<rtcp::RtcpPacket>(bye);
}
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
const RtcpContext& ctx) {
rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
xr->SetSenderSsrc(ssrc_);
if (!sending_ && xr_send_receiver_reference_time_enabled_) {
rtcp::Rrtr rrtr;
rrtr.SetNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
xr->SetRrtr(rrtr);
}
// TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
return std::unique_ptr<rtcp::RtcpPacket>(xr);
}
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
const RtcpContext& ctx) {
rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
xr->SetSenderSsrc(ssrc_);
RTC_DCHECK(ctx.feedback_state_.has_last_xr_rr);
if (ctx.feedback_state_.has_last_xr_rr) {
xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
}
return std::unique_ptr<rtcp::RtcpPacket>(xr);
}
if (video_bitrate_allocation_) {
rtcp::TargetBitrate target_bitrate;
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
const RtcpContext& context) {
rtcp::ExtendedReports* xr = new rtcp::ExtendedReports();
xr->SetSenderSsrc(ssrc_);
for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
uint32_t layer_bitrate_bps =
video_bitrate_allocation_->GetBitrate(sl, tl);
if (layer_bitrate_bps > 0)
target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
}
}
xr->SetTargetBitrate(target_bitrate);
video_bitrate_allocation_.reset();
}
if (xr_voip_metric_) {
rtcp::VoipMetric voip;
voip.SetMediaSsrc(remote_ssrc_);
voip.SetVoipMetric(xr_voip_metric_);
voip.SetVoipMetric(*xr_voip_metric_);
xr_voip_metric_.reset();
xr->SetVoipMetric(voip);
}
return std::unique_ptr<rtcp::RtcpPacket>(xr);
return std::move(xr);
}
int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
@ -794,7 +800,8 @@ int32_t RTCPSender::SendCompoundRTCP(
auto it = report_flags_.begin();
while (it != report_flags_.end()) {
auto builder_it = builders_.find(it->type);
RTC_DCHECK(builder_it != builders_.end());
RTC_DCHECK(builder_it != builders_.end())
<< "Could not find builder for packet type " << it->type;
if (it->is_volatile) {
report_flags_.erase(it++);
} else {
@ -849,10 +856,10 @@ void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
SetFlag(kRtcpSdes, true);
if (generate_report) {
if (!sending_ && xr_send_receiver_reference_time_enabled_)
SetFlag(kRtcpXrReceiverReferenceTime, true);
if (feedback_state.has_last_xr_rr)
SetFlag(kRtcpXrDlrrReportBlock, true);
if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
SetFlag(kRtcpAnyExtendedReports, true);
}
// generate next time to send an RTCP report
uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
@ -959,9 +966,9 @@ int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
rtc::CritScope lock(&critical_section_rtcp_sender_);
memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
xr_voip_metric_.emplace(*VoIPMetric);
SetFlag(kRtcpXrVoipMetric, true);
SetFlag(kRtcpAnyExtendedReports, true);
return 0;
}
@ -981,8 +988,12 @@ void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
SetFlag(kRtcpTmmbn, true);
}
void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
if (type & kRtcpAnyExtendedReports) {
report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
} else {
report_flags_.insert(ReportFlag(type, is_volatile));
}
}
void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
@ -991,11 +1002,11 @@ void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
SetFlag(type, is_volatile);
}
bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
bool RTCPSender::IsFlagPresent(uint32_t type) const {
return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
}
bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
auto it = report_flags_.find(ReportFlag(type, false));
if (it == report_flags_.end())
return false;
@ -1012,6 +1023,12 @@ bool RTCPSender::AllVolatileFlagsConsumed() const {
return true;
}
void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
rtc::CritScope lock(&critical_section_rtcp_sender_);
video_bitrate_allocation_.emplace(bitrate);
SetFlag(kRtcpAnyExtendedReports, true);
}
bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
public:

View File

@ -21,6 +21,7 @@
#include "webrtc/api/call/transport.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/optional.h"
#include "webrtc/base/random.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
@ -150,6 +151,7 @@ class RTCPSender {
void SetCsrcs(const std::vector<uint32_t>& csrcs);
void SetTargetBitrate(unsigned int target_bitrate);
void SetVideoBitrateAllocation(const BitrateAllocation& bitrate);
bool SendFeedbackPacket(const rtcp::TransportFeedback& packet);
private:
@ -180,7 +182,8 @@ class RTCPSender {
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildAPP(const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildVoIPMetric(const RtcpContext& context)
std::unique_ptr<rtcp::RtcpPacket> BuildExtendedReports(
const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildBYE(const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
@ -192,11 +195,6 @@ class RTCPSender {
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildNACK(const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildReceiverReferenceTime(
const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
std::unique_ptr<rtcp::RtcpPacket> BuildDlrr(const RtcpContext& context)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
private:
const bool audio_;
@ -257,7 +255,8 @@ class RTCPSender {
GUARDED_BY(critical_section_rtcp_sender_);
// XR VoIP metric
RTCPVoIPMetric xr_voip_metric_ GUARDED_BY(critical_section_rtcp_sender_);
rtc::Optional<RTCPVoIPMetric> xr_voip_metric_
GUARDED_BY(critical_section_rtcp_sender_);
RtcpPacketTypeCounterObserver* const packet_type_counter_observer_;
RtcpPacketTypeCounter packet_type_counter_
@ -265,22 +264,25 @@ class RTCPSender {
RTCPUtility::NackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_);
void SetFlag(RTCPPacketType type, bool is_volatile)
rtc::Optional<BitrateAllocation> video_bitrate_allocation_
GUARDED_BY(critical_section_rtcp_sender_);
void SetFlag(uint32_t type, bool is_volatile)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
void SetFlags(const std::set<RTCPPacketType>& types, bool is_volatile)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
bool IsFlagPresent(RTCPPacketType type) const
bool IsFlagPresent(uint32_t type) const
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
bool ConsumeFlag(RTCPPacketType type, bool forced = false)
bool ConsumeFlag(uint32_t type, bool forced = false)
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
bool AllVolatileFlagsConsumed() const
EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
struct ReportFlag {
ReportFlag(RTCPPacketType type, bool is_volatile)
ReportFlag(uint32_t type, bool is_volatile)
: type(type), is_volatile(is_volatile) {}
bool operator<(const ReportFlag& flag) const { return type < flag.type; }
bool operator==(const ReportFlag& flag) const { return type == flag.type; }
const RTCPPacketType type;
const uint32_t type;
const bool is_volatile;
};
@ -288,7 +290,8 @@ class RTCPSender {
typedef std::unique_ptr<rtcp::RtcpPacket> (RTCPSender::*BuilderFunc)(
const RtcpContext&);
std::map<RTCPPacketType, BuilderFunc> builders_;
// Map from RTCPPacketType to builder.
std::map<uint32_t, BuilderFunc> builders_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTCPSender);
};

View File

@ -821,4 +821,39 @@ TEST_F(RtcpSenderTest, ByeMustBeLast) {
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpBye));
}
TEST_F(RtcpSenderTest, SendXrWithTargetBitrate) {
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
const size_t kNumSpatialLayers = 2;
const size_t kNumTemporalLayers = 2;
BitrateAllocation allocation;
for (size_t sl = 0; sl < kNumSpatialLayers; ++sl) {
uint32_t start_bitrate_bps = (sl + 1) * 100000;
for (size_t tl = 0; tl < kNumTemporalLayers; ++tl)
allocation.SetBitrate(sl, tl, start_bitrate_bps + (tl * 20000));
}
rtcp_sender_->SetVideoBitrateAllocation(allocation);
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
EXPECT_EQ(1, parser()->xr()->num_packets());
EXPECT_EQ(kSenderSsrc, parser()->xr()->sender_ssrc());
const rtc::Optional<rtcp::TargetBitrate>& target_bitrate =
parser()->xr()->target_bitrate();
ASSERT_TRUE(target_bitrate);
const std::vector<rtcp::TargetBitrate::BitrateItem>& bitrates =
target_bitrate->GetTargetBitrates();
EXPECT_EQ(kNumSpatialLayers * kNumTemporalLayers, bitrates.size());
for (size_t sl = 0; sl < kNumSpatialLayers; ++sl) {
uint32_t start_bitrate_bps = (sl + 1) * 100000;
for (size_t tl = 0; tl < kNumTemporalLayers; ++tl) {
size_t index = (sl * kNumSpatialLayers) + tl;
const rtcp::TargetBitrate::BitrateItem& item = bitrates[index];
EXPECT_EQ(sl, item.spatial_layer);
EXPECT_EQ(tl, item.temporal_layer);
EXPECT_EQ(start_bitrate_bps + (tl * 20000),
item.target_bitrate_kbps * 1000);
}
}
}
} // namespace webrtc

View File

@ -953,4 +953,9 @@ StreamDataCountersCallback*
ModuleRtpRtcpImpl::GetSendChannelRtpStatisticsCallback() const {
return rtp_sender_.GetRtpStatisticsCallback();
}
void ModuleRtpRtcpImpl::SetVideoBitrateAllocation(
const BitrateAllocation& bitrate) {
rtcp_sender_.SetVideoBitrateAllocation(bitrate);
}
} // namespace webrtc

View File

@ -313,6 +313,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
const ReportBlockList& report_blocks) override;
void OnRequestSendReport() override;
void SetVideoBitrateAllocation(const BitrateAllocation& bitrate) override;
protected:
bool UpdateRTCPReceiveInformationTimers();