Implements start bitrate for new video API.
Added a new rampup test.
BUG=2879
R=pbos@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/15769004
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@6443 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/call.h b/call.h
index 1771ad8..480d73e 100644
--- a/call.h
+++ b/call.h
@@ -61,7 +61,8 @@
: webrtc_config(NULL),
send_transport(send_transport),
voice_engine(NULL),
- overuse_callback(NULL) {}
+ overuse_callback(NULL),
+ start_bitrate_bps(-1) {}
webrtc::Config* webrtc_config;
@@ -73,6 +74,11 @@
// Callback for overuse and normal usage based on the jitter of incoming
// captured frames. 'NULL' disables the callback.
OveruseCallback* overuse_callback;
+
+ // Start bitrate used before a valid bitrate estimate is calculated. '-1'
+ // lets the call decide start bitrate.
+ // Note: This currently only affects video.
+ int start_bitrate_bps;
};
static Call* Create(const Call::Config& config);
diff --git a/video/call.cc b/video/call.cc
index 6103074..6daa8b0 100644
--- a/video/call.cc
+++ b/video/call.cc
@@ -131,6 +131,8 @@
namespace internal {
+const int kDefaultVideoStreamBitrateBps = 300000;
+
Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
: config_(config),
receive_lock_(RWLockWrapper::CreateRWLock()),
@@ -182,14 +184,18 @@
const void* encoder_settings) {
assert(config.rtp.ssrcs.size() > 0);
- VideoSendStream* send_stream =
- new VideoSendStream(config_.send_transport,
- overuse_observer_proxy_.get(),
- video_engine_,
- config,
- video_streams,
- encoder_settings,
- base_channel_id_);
+ // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if
+ // the call has already started.
+ VideoSendStream* send_stream = new VideoSendStream(
+ config_.send_transport,
+ overuse_observer_proxy_.get(),
+ video_engine_,
+ config,
+ video_streams,
+ encoder_settings,
+ base_channel_id_,
+ config_.start_bitrate_bps != -1 ? config_.start_bitrate_bps
+ : kDefaultVideoStreamBitrateBps);
WriteLockScoped write_lock(*send_lock_);
for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
diff --git a/video/loopback.cc b/video/loopback.cc
index ecc2089..ea65ebb 100644
--- a/video/loopback.cc
+++ b/video/loopback.cc
@@ -61,6 +61,8 @@
test::DirectTransport transport;
Call::Config call_config(&transport);
+ call_config.start_bitrate_bps =
+ static_cast<int>(flags::StartBitrate()) * 1000;
scoped_ptr<Call> call(Call::Create(call_config));
// Loopback, call sends to itself.
diff --git a/video/rampup_tests.cc b/video/rampup_tests.cc
index 86950ce..94f1c19 100644
--- a/video/rampup_tests.cc
+++ b/video/rampup_tests.cc
@@ -40,6 +40,7 @@
namespace {
static const int kTransmissionTimeOffsetExtensionId = 6;
static const int kMaxPacketSize = 1500;
+static const unsigned int kSingleStreamTargetBps = 1000000;
class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
public:
@@ -57,6 +58,7 @@
new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(false))),
crit_(CriticalSectionWrapper::CreateCriticalSection()),
expected_bitrate_bps_(0),
+ start_bitrate_bps_(0),
rtx_media_ssrcs_(rtx_media_ssrcs),
total_sent_(0),
padding_sent_(0),
@@ -89,10 +91,25 @@
expected_bitrate_bps_ = expected_bitrate_bps;
}
+ void set_start_bitrate_bps(unsigned int start_bitrate_bps) {
+ CriticalSectionScoped lock(crit_.get());
+ start_bitrate_bps_ = start_bitrate_bps;
+ }
+
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
unsigned int bitrate) OVERRIDE {
CriticalSectionScoped lock(crit_.get());
assert(expected_bitrate_bps_ > 0);
+ if (start_bitrate_bps_ != 0) {
+ // For tests with an explicitly set start bitrate, verify the first
+ // bitrate estimate is close to the start bitrate and lower than the
+ // test target bitrate. This is to verify a call respects the configured
+ // start bitrate, but due to the BWE implementation we can't guarantee the
+ // first estimate really is as high as the start bitrate.
+ EXPECT_GT(bitrate, 0.9 * start_bitrate_bps_);
+ EXPECT_LT(bitrate, expected_bitrate_bps_);
+ start_bitrate_bps_ = 0;
+ }
if (bitrate >= expected_bitrate_bps_) {
// Just trigger if there was any rtx padding packet.
if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
@@ -178,6 +195,7 @@
const scoped_ptr<CriticalSectionWrapper> crit_;
unsigned int expected_bitrate_bps_ GUARDED_BY(crit_);
+ unsigned int start_bitrate_bps_ GUARDED_BY(crit_);
SsrcMap rtx_media_ssrcs_ GUARDED_BY(crit_);
size_t total_sent_ GUARDED_BY(crit_);
size_t padding_sent_ GUARDED_BY(crit_);
@@ -400,14 +418,16 @@
size_t total_overuse_bytes_ GUARDED_BY(crit_);
bool suspended_in_stats_ GUARDED_BY(crit_);
};
-}
+} // namespace
class RampUpTest : public ::testing::Test {
public:
virtual void SetUp() { reserved_ssrcs_.clear(); }
protected:
- void RunRampUpTest(bool rtx, size_t num_streams) {
+ void RunRampUpTest(bool rtx,
+ size_t num_streams,
+ unsigned int start_bitrate_bps) {
std::vector<uint32_t> ssrcs(GenerateSsrcs(num_streams, 100));
std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(num_streams, 200));
StreamObserver::SsrcMap rtx_ssrc_map;
@@ -421,6 +441,10 @@
Clock::GetRealTimeClock());
Call::Config call_config(&stream_observer);
+ if (start_bitrate_bps != 0) {
+ call_config.start_bitrate_bps = start_bitrate_bps;
+ stream_observer.set_start_bitrate_bps(start_bitrate_bps);
+ }
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = call->GetDefaultSendConfig();
@@ -451,10 +475,10 @@
if (num_streams == 1) {
// For single stream rampup until 1mbps
- stream_observer.set_expected_bitrate_bps(1000000);
+ stream_observer.set_expected_bitrate_bps(kSingleStreamTargetBps);
} else {
// For multi stream rampup until all streams are being sent. That means
- // enough birate to sent all the target streams plus the min bitrate of
+ // enough birate to send all the target streams plus the min bitrate of
// the last one.
int expected_bitrate_bps = video_streams.back().min_bitrate_bps;
for (size_t i = 0; i < video_streams.size() - 1; ++i) {
@@ -564,15 +588,19 @@
};
TEST_F(RampUpTest, SingleStream) {
- RunRampUpTest(false, 1);
+ RunRampUpTest(false, 1, 0);
}
TEST_F(RampUpTest, Simulcast) {
- RunRampUpTest(false, 3);
+ RunRampUpTest(false, 3, 0);
}
TEST_F(RampUpTest, SimulcastWithRtx) {
- RunRampUpTest(true, 3);
+ RunRampUpTest(true, 3, 0);
+}
+
+TEST_F(RampUpTest, SingleStreamWithHighStartBitrate) {
+ RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps);
}
TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
index 170badc..f9bbd57 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -114,16 +114,19 @@
const VideoSendStream::Config& config,
const std::vector<VideoStream> video_streams,
const void* encoder_settings,
- int base_channel)
+ int base_channel,
+ int start_bitrate_bps)
: transport_adapter_(transport),
encoded_frame_proxy_(config.post_encode_callback),
config_(config),
+ start_bitrate_bps_(start_bitrate_bps),
external_codec_(NULL),
channel_(-1),
stats_proxy_(new SendStatisticsProxy(config, this)) {
video_engine_base_ = ViEBase::GetInterface(video_engine);
video_engine_base_->CreateChannel(channel_, base_channel);
assert(channel_ != -1);
+ assert(start_bitrate_bps_ > 0);
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
assert(rtp_rtcp_ != NULL);
@@ -350,13 +353,17 @@
video_codec.qpMax = std::max(video_codec.qpMax,
static_cast<unsigned int>(streams[i].max_qp));
}
+ video_codec.startBitrate =
+ static_cast<unsigned int>(start_bitrate_bps_) / 1000;
if (video_codec.minBitrate < kViEMinCodecBitrate)
video_codec.minBitrate = kViEMinCodecBitrate;
if (video_codec.maxBitrate < kViEMinCodecBitrate)
video_codec.maxBitrate = kViEMinCodecBitrate;
-
- video_codec.startBitrate = 300;
+ if (video_codec.startBitrate < video_codec.minBitrate)
+ video_codec.startBitrate = video_codec.minBitrate;
+ if (video_codec.startBitrate > video_codec.maxBitrate)
+ video_codec.startBitrate = video_codec.maxBitrate;
if (video_codec.startBitrate < video_codec.minBitrate)
video_codec.startBitrate = video_codec.minBitrate;
diff --git a/video/video_send_stream.h b/video/video_send_stream.h
index 125c7fd..ed77665 100644
--- a/video/video_send_stream.h
+++ b/video/video_send_stream.h
@@ -44,7 +44,8 @@
const VideoSendStream::Config& config,
const std::vector<VideoStream> video_streams,
const void* encoder_settings,
- int base_channel);
+ int base_channel,
+ int start_bitrate);
virtual ~VideoSendStream();
@@ -73,6 +74,7 @@
TransportAdapter transport_adapter_;
EncodedFrameCallbackAdapter encoded_frame_proxy_;
const VideoSendStream::Config config_;
+ const int start_bitrate_bps_;
ViEBase* video_engine_base_;
ViECapture* capture_;