Remove overhead from video bitrate.

BUG=webrtc:6638

Review-Url: https://codereview.webrtc.org/2517243005
Cr-Commit-Position: refs/heads/master@{#15303}
This commit is contained in:
michaelt 2016-11-29 09:25:03 -08:00 committed by Commit bot
parent c4dc4a5956
commit a33287761a
2 changed files with 122 additions and 15 deletions

View File

@ -27,6 +27,7 @@
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
#include "webrtc/modules/utility/include/process_thread.h"
#include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
#include "webrtc/system_wrappers/include/field_trial.h"
#include "webrtc/video/call_stats.h"
#include "webrtc/video/vie_remb.h"
#include "webrtc/video_send_stream.h"
@ -49,6 +50,7 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules(
SendDelayStats* send_delay_stats,
RtcEventLog* event_log,
RateLimiter* retransmission_rate_limiter,
OverheadObserver* overhead_observer,
size_t num_modules) {
RTC_DCHECK_GT(num_modules, 0);
RtpRtcp::Configuration configuration;
@ -72,7 +74,7 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules(
configuration.send_packet_observer = send_delay_stats;
configuration.event_log = event_log;
configuration.retransmission_rate_limiter = retransmission_rate_limiter;
configuration.overhead_observer = overhead_observer;
std::vector<RtpRtcp*> modules;
for (size_t i = 0; i < num_modules; ++i) {
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
@ -284,6 +286,7 @@ namespace internal {
// An encoder may deliver frames through the EncodedImageCallback on an
// arbitrary thread.
class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
public webrtc::OverheadObserver,
public webrtc::VCMProtectionCallback,
public ViEEncoder::EncoderSink {
public:
@ -337,6 +340,9 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps) override;
// Implements OverheadObserver.
void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
int min_transmit_bitrate_bps) override;
@ -398,6 +404,10 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
// |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
// invalidated before any other members are destroyed.
rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
rtc::CriticalSection overhead_bytes_per_packet_crit_;
size_t overhead_bytes_per_packet_ GUARDED_BY(overhead_bytes_per_packet_crit_);
size_t transport_overhead_bytes_per_packet_;
};
// TODO(tommi): See if there's a more elegant way to create a task that creates
@ -734,10 +744,13 @@ VideoSendStreamImpl::VideoSendStreamImpl(
send_delay_stats,
event_log,
congestion_controller_->GetRetransmissionRateLimiter(),
this,
config_->rtp.ssrcs.size())),
payload_router_(rtp_rtcp_modules_,
config_->encoder_settings.payload_type),
weak_ptr_factory_(this) {
weak_ptr_factory_(this),
overhead_bytes_per_packet_(0),
transport_overhead_bytes_per_packet_(0) {
RTC_DCHECK_RUN_ON(worker_queue_);
LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
@ -777,15 +790,12 @@ VideoSendStreamImpl::VideoSendStreamImpl(
// TODO(pbos): Should we set CNAME on all RTP modules?
rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
// 28 to match packet overhead in ModuleRtpRtcpImpl.
static const size_t kRtpPacketSizeOverhead = 28;
RTC_DCHECK_LE(config_->rtp.max_packet_size, 0xFFFFu + kRtpPacketSizeOverhead);
const uint16_t mtu = static_cast<uint16_t>(config_->rtp.max_packet_size +
kRtpPacketSizeOverhead);
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
rtp_rtcp->SetMaxTransferUnit(mtu);
rtp_rtcp->SetMaxTransferUnit(
static_cast<uint16_t>(config_->rtp.max_packet_size));
rtp_rtcp->RegisterVideoSendPayload(
config_->encoder_settings.payload_type,
config_->encoder_settings.payload_name.c_str());
@ -1155,6 +1165,19 @@ uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
RTC_DCHECK_RUN_ON(worker_queue_);
RTC_DCHECK(payload_router_.active())
<< "VideoSendStream::Start has not been called.";
if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
"Enabled") {
// Substract overhead from bitrate.
rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
int packets_per_second =
std::ceil(bitrate_bps / (8 * (config_->rtp.max_packet_size +
transport_overhead_bytes_per_packet_)));
uint32_t overhead_bps = static_cast<uint32_t>(
8 * overhead_bytes_per_packet_ * packets_per_second);
bitrate_bps = overhead_bps > bitrate_bps ? 0u : bitrate_bps - overhead_bps;
}
// Get the encoder target rate. It is the estimated network rate -
// protection overhead.
encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
@ -1214,10 +1237,22 @@ int VideoSendStreamImpl::ProtectionRequest(
return 0;
}
void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
overhead_bytes_per_packet_ = overhead_bytes_per_packet;
}
void VideoSendStreamImpl::SetTransportOverhead(
int transport_overhead_per_packet) {
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
rtp_rtcp->SetTransportOverhead(transport_overhead_per_packet);
int transport_overhead_bytes_per_packet) {
transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
RTC_DCHECK_LE(config_->rtp.max_packet_size,
0xFFFFu + transport_overhead_bytes_per_packet);
const uint16_t mtu = static_cast<uint16_t>(
config_->rtp.max_packet_size + transport_overhead_bytes_per_packet);
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
rtp_rtcp->SetTransportOverhead(transport_overhead_bytes_per_packet);
rtp_rtcp->SetMaxTransferUnit(mtu);
}
}
} // namespace internal

View File

@ -36,6 +36,7 @@
#include "webrtc/test/null_transport.h"
#include "webrtc/test/rtcp_packet_parser.h"
#include "webrtc/test/testsupport/perf_test.h"
#include "webrtc/test/field_trial.h"
#include "webrtc/video/send_statistics_proxy.h"
#include "webrtc/video/transport_adapter.h"
@ -1502,21 +1503,27 @@ TEST_F(VideoSendStreamTest, ChangingTransportOverhead) {
}
Action OnSendRtp(const uint8_t* packet, size_t length) override {
EXPECT_LE(length,
IP_PACKET_SIZE - static_cast<size_t>(transport_overhead_));
EXPECT_LE(length, kMaxRtpPacketSize);
if (++packets_sent_ < 100)
return SEND_PACKET;
observation_complete_.Set();
return SEND_PACKET;
}
void ModifyVideoConfigs(
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* receive_configs,
VideoEncoderConfig* encoder_config) override {
send_config->rtp.max_packet_size = kMaxRtpPacketSize;
}
void PerformTest() override {
transport_overhead_ = 500;
transport_overhead_ = 100;
call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO,
transport_overhead_);
EXPECT_TRUE(Wait());
packets_sent_ = 0;
transport_overhead_ = 1000;
transport_overhead_ = 500;
call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO,
transport_overhead_);
EXPECT_TRUE(Wait());
@ -1526,6 +1533,7 @@ TEST_F(VideoSendStreamTest, ChangingTransportOverhead) {
Call* call_;
int packets_sent_;
int transport_overhead_;
const size_t kMaxRtpPacketSize = 1000;
} test;
RunBaseTest(&test);
@ -3173,4 +3181,68 @@ TEST_F(VideoSendStreamTest,
TestRequestSourceRotateVideo(true);
}
// This test verifies that overhead is removed from the bandwidth estimate by
// testing that the maximum possible target payload rate is smaller than the
// maximum bandwidth estimate by the overhead rate.
TEST_F(VideoSendStreamTest, RemoveOverheadFromBandwidth) {
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
class RemoveOverheadFromBandwidthTest : public test::EndToEndTest,
public test::FakeEncoder {
public:
RemoveOverheadFromBandwidthTest()
: EndToEndTest(test::CallTest::kDefaultTimeoutMs),
FakeEncoder(Clock::GetRealTimeClock()),
call_(nullptr),
max_bitrate_kbps_(0) {}
int32_t SetRateAllocation(const BitrateAllocation& bitrate,
uint32_t frameRate) override {
rtc::CritScope lock(&crit_);
if (max_bitrate_kbps_ < bitrate.get_sum_kbps())
max_bitrate_kbps_ = bitrate.get_sum_kbps();
return FakeEncoder::SetRateAllocation(bitrate, frameRate);
}
void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
call_ = sender_call;
}
void ModifyVideoConfigs(
VideoSendStream::Config* send_config,
std::vector<VideoReceiveStream::Config>* receive_configs,
VideoEncoderConfig* encoder_config) override {
send_config->rtp.max_packet_size = 1200;
send_config->encoder_settings.encoder = this;
EXPECT_FALSE(send_config->rtp.extensions.empty());
}
void PerformTest() override {
call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO, 20);
Call::Config::BitrateConfig bitrate_config;
constexpr int kStartBitrateBps = 50000;
constexpr int kMaxBitrateBps = 60000;
bitrate_config.start_bitrate_bps = kStartBitrateBps;
bitrate_config.max_bitrate_bps = kMaxBitrateBps;
call_->SetBitrateConfig(bitrate_config);
// At a bitrate of 60kbps with a packet size of 1200B video and an
// overhead of 40B per packet video produces 2kbps overhead.
// So with a BWE should reach 58kbps but not 60kbps.
Wait();
{
rtc::CritScope lock(&crit_);
EXPECT_EQ(58u, max_bitrate_kbps_);
}
}
private:
Call* call_;
rtc::CriticalSection crit_;
uint32_t max_bitrate_kbps_ GUARDED_BY(&crit_);
} test;
RunBaseTest(&test);
}
} // namespace webrtc