Implement settable min/start/max bitrates in Call.
These parameters are set by the x-google-*-bitrate SDP parameters. This is implemented on a Call level instead of per-stream like the currently underlying VideoEngine implementation to allow this refactoring to not reconfigure the VideoCodec at all but rather adjust bandwidth-estimator parameters. Also implements SetMaxSendBandwidth in WebRtcVideoEngine2 as it's a SDP parameter and allowing it to be dynamically readjusted in Call. R=mflodman@webrtc.org, stefan@webrtc.org BUG=1788 Review URL: https://webrtc-codereview.appspot.com/26199004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7746 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b951eb12c9
commit
008731868a
@ -200,18 +200,8 @@ std::vector<webrtc::VideoStream> WebRtcVideoEncoderFactory2::CreateVideoStreams(
|
||||
stream.max_framerate =
|
||||
codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
|
||||
|
||||
int min_bitrate = kMinVideoBitrate;
|
||||
codec.GetParam(kCodecParamMinBitrate, &min_bitrate);
|
||||
// Clamp the min video bitrate, this is set from JavaScript directly and needs
|
||||
// to be sanitized.
|
||||
if (min_bitrate < kMinVideoBitrate) {
|
||||
min_bitrate = kMinVideoBitrate;
|
||||
}
|
||||
|
||||
int max_bitrate = kMaxVideoBitrate;
|
||||
codec.GetParam(kCodecParamMaxBitrate, &max_bitrate);
|
||||
stream.min_bitrate_bps = min_bitrate * 1000;
|
||||
stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate * 1000;
|
||||
stream.min_bitrate_bps = kMinVideoBitrate * 1000;
|
||||
stream.target_bitrate_bps = stream.max_bitrate_bps = kMaxVideoBitrate * 1000;
|
||||
|
||||
int max_qp = kDefaultQpMax;
|
||||
codec.GetParam(kCodecParamMaxQuantization, &max_qp);
|
||||
@ -703,11 +693,6 @@ WebRtcVideoChannel2::WebRtcVideoChannel2(
|
||||
config.voice_engine = voice_engine->voe()->engine();
|
||||
}
|
||||
|
||||
// Set start bitrate for the call. A default is provided by SetDefaultOptions.
|
||||
int start_bitrate_kbps;
|
||||
options_.video_start_bitrate.Get(&start_bitrate_kbps);
|
||||
config.stream_start_bitrate_bps = start_bitrate_kbps * 1000;
|
||||
|
||||
call_.reset(call_factory->CreateCall(config));
|
||||
|
||||
rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
|
||||
@ -721,8 +706,6 @@ void WebRtcVideoChannel2::SetDefaultOptions() {
|
||||
options_.suspend_below_min_bitrate.Set(false);
|
||||
options_.use_payload_padding.Set(false);
|
||||
options_.video_noise_reduction.Set(true);
|
||||
options_.video_start_bitrate.Set(
|
||||
webrtc::Call::Config::kDefaultStartBitrateBps / 1000);
|
||||
options_.screencast_min_bitrate.Set(0);
|
||||
}
|
||||
|
||||
@ -841,6 +824,29 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
|
||||
it->second->SetCodec(supported_codecs.front());
|
||||
}
|
||||
|
||||
VideoCodec codec = supported_codecs.front().codec;
|
||||
int bitrate_kbps;
|
||||
if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
|
||||
bitrate_kbps > 0) {
|
||||
bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000;
|
||||
} else {
|
||||
bitrate_config_.min_bitrate_bps = 0;
|
||||
}
|
||||
if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
|
||||
bitrate_kbps > 0) {
|
||||
bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000;
|
||||
} else {
|
||||
// Do not reconfigure start bitrate unless it's specified and positive.
|
||||
bitrate_config_.start_bitrate_bps = -1;
|
||||
}
|
||||
if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
|
||||
bitrate_kbps > 0) {
|
||||
bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000;
|
||||
} else {
|
||||
bitrate_config_.max_bitrate_bps = -1;
|
||||
}
|
||||
call_->SetBitrateConfig(bitrate_config_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1276,9 +1282,19 @@ bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcVideoChannel2::SetMaxSendBandwidth(int bps) {
|
||||
// TODO(pbos): Implement.
|
||||
LOG(LS_VERBOSE) << "SetMaxSendBandwidth: " << bps;
|
||||
bool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) {
|
||||
LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps.";
|
||||
if (max_bitrate_bps <= 0) {
|
||||
// Unsetting max bitrate.
|
||||
max_bitrate_bps = -1;
|
||||
}
|
||||
bitrate_config_.start_bitrate_bps = -1;
|
||||
bitrate_config_.max_bitrate_bps = max_bitrate_bps;
|
||||
if (max_bitrate_bps > 0 &&
|
||||
bitrate_config_.min_bitrate_bps > max_bitrate_bps) {
|
||||
bitrate_config_.min_bitrate_bps = max_bitrate_bps;
|
||||
}
|
||||
call_->SetBitrateConfig(bitrate_config_);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -491,6 +491,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler,
|
||||
WebRtcVideoEncoderFactory2* const encoder_factory_;
|
||||
std::vector<VideoCodecSettings> recv_codecs_;
|
||||
std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
|
||||
webrtc::Call::Config::BitrateConfig bitrate_config_;
|
||||
VideoOptions options_;
|
||||
};
|
||||
|
||||
|
@ -299,6 +299,11 @@ webrtc::Call::Stats FakeCall::GetStats() const {
|
||||
return stats;
|
||||
}
|
||||
|
||||
void FakeCall::SetBitrateConfig(
|
||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) {
|
||||
config_.stream_bitrates = bitrate_config;
|
||||
}
|
||||
|
||||
void FakeCall::SignalNetworkState(webrtc::Call::NetworkState state) {
|
||||
network_state_ = state;
|
||||
}
|
||||
@ -350,8 +355,6 @@ class WebRtcVideoEngine2Test : public ::testing::Test {
|
||||
cricket::WebRtcVideoDecoderFactory* decoder_factory,
|
||||
const std::vector<VideoCodec>& codecs);
|
||||
|
||||
void TestStartBitrate(bool override_start_bitrate, int start_bitrate_bps);
|
||||
|
||||
WebRtcVideoEngine2 engine_;
|
||||
VideoCodec default_codec_;
|
||||
VideoCodec default_red_codec_;
|
||||
@ -480,39 +483,6 @@ TEST_F(WebRtcVideoEngine2Test, SupportsAbsoluteSenderTimeHeaderExtension) {
|
||||
FAIL() << "Absolute Sender Time extension not in header-extension list.";
|
||||
}
|
||||
|
||||
void WebRtcVideoEngine2Test::TestStartBitrate(bool override_start_bitrate,
|
||||
int start_bitrate_bps) {
|
||||
FakeCallFactory call_factory;
|
||||
engine_.SetCallFactory(&call_factory);
|
||||
|
||||
engine_.Init(rtc::Thread::Current());
|
||||
|
||||
cricket::VideoOptions options;
|
||||
if (override_start_bitrate) {
|
||||
options.video_start_bitrate.Set(start_bitrate_bps / 1000);
|
||||
}
|
||||
|
||||
rtc::scoped_ptr<VideoMediaChannel> channel(
|
||||
engine_.CreateChannel(options, NULL));
|
||||
|
||||
EXPECT_EQ(override_start_bitrate
|
||||
? start_bitrate_bps
|
||||
: webrtc::Call::Config::kDefaultStartBitrateBps,
|
||||
call_factory.GetCall()->GetConfig().stream_start_bitrate_bps);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, UsesCorrectDefaultStartBitrate) {
|
||||
TestStartBitrate(false, -1);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, CreateChannelCanUseIncreasedStartBitrate) {
|
||||
TestStartBitrate(true, 2 * webrtc::Call::Config::kDefaultStartBitrateBps);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, CreateChannelCanUseDecreasedStartBitrate) {
|
||||
TestStartBitrate(true, webrtc::Call::Config::kDefaultStartBitrateBps / 2);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, SetSendFailsBeforeSettingCodecs) {
|
||||
engine_.Init(rtc::Thread::Current());
|
||||
rtc::scoped_ptr<VideoMediaChannel> channel(
|
||||
@ -877,25 +847,25 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test,
|
||||
return streams[streams.size() - 1];
|
||||
}
|
||||
|
||||
void SetSendCodecsShouldWorkForBitrates(const char* min_bitrate,
|
||||
const char* max_bitrate) {
|
||||
void SetSendCodecsShouldWorkForBitrates(const char* min_bitrate_kbps,
|
||||
int expected_min_bitrate_bps,
|
||||
const char* start_bitrate_kbps,
|
||||
int expected_start_bitrate_bps,
|
||||
const char* max_bitrate_kbps,
|
||||
int expected_max_bitrate_bps) {
|
||||
std::vector<VideoCodec> codecs;
|
||||
codecs.push_back(kVp8Codec);
|
||||
codecs[0].params[kCodecParamMinBitrate] = min_bitrate;
|
||||
codecs[0].params[kCodecParamMaxBitrate] = max_bitrate;
|
||||
codecs[0].params[kCodecParamMinBitrate] = min_bitrate_kbps;
|
||||
codecs[0].params[kCodecParamStartBitrate] = start_bitrate_kbps;
|
||||
codecs[0].params[kCodecParamMaxBitrate] = max_bitrate_kbps;
|
||||
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
|
||||
|
||||
FakeVideoSendStream* stream = AddSendStream();
|
||||
|
||||
std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
|
||||
ASSERT_EQ(1u, video_streams.size());
|
||||
EXPECT_EQ(atoi(min_bitrate), video_streams.back().min_bitrate_bps / 1000);
|
||||
EXPECT_EQ(atoi(max_bitrate), video_streams.back().max_bitrate_bps / 1000);
|
||||
|
||||
VideoCodec codec;
|
||||
EXPECT_TRUE(channel_->GetSendCodec(&codec));
|
||||
EXPECT_EQ(min_bitrate, codec.params[kCodecParamMinBitrate]);
|
||||
EXPECT_EQ(max_bitrate, codec.params[kCodecParamMaxBitrate]);
|
||||
EXPECT_EQ(expected_min_bitrate_bps,
|
||||
fake_call_->GetConfig().stream_bitrates.min_bitrate_bps);
|
||||
EXPECT_EQ(expected_start_bitrate_bps,
|
||||
fake_call_->GetConfig().stream_bitrates.start_bitrate_bps);
|
||||
EXPECT_EQ(expected_max_bitrate_bps,
|
||||
fake_call_->GetConfig().stream_bitrates.max_bitrate_bps);
|
||||
}
|
||||
|
||||
void TestSetSendRtpHeaderExtensions(const std::string& cricket_ext,
|
||||
@ -1630,8 +1600,19 @@ TEST_F(WebRtcVideoChannel2Test, SetSendCodecsChangesExistingStreams) {
|
||||
EXPECT_EQ(kVp8Codec360p.height, streams[0].height);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithMinMaxBitrate) {
|
||||
SetSendCodecsShouldWorkForBitrates("100", "200");
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithBitrates) {
|
||||
SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
|
||||
200000);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test,
|
||||
SetSendCodecsWithoutBitratesUsesCorrectDefaults) {
|
||||
SetSendCodecsShouldWorkForBitrates(
|
||||
"", 0, "", -1, "", -1);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsCapsMinAndStartBitrate) {
|
||||
SetSendCodecsShouldWorkForBitrates("-1", 0, "-100", -1, "", -1);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectsMaxLessThanMinBitrate) {
|
||||
@ -1641,8 +1622,25 @@ TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectsMaxLessThanMinBitrate) {
|
||||
EXPECT_FALSE(channel_->SetSendCodecs(video_codecs));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsAcceptLargeMinMaxBitrate) {
|
||||
SetSendCodecsShouldWorkForBitrates("1000", "2000");
|
||||
TEST_F(WebRtcVideoChannel2Test,
|
||||
SetMaxSendBandwidthShouldPreserveOtherBitrates) {
|
||||
SetSendCodecsShouldWorkForBitrates("100", 100000, "150", 150000, "200",
|
||||
200000);
|
||||
channel_->SetMaxSendBandwidth(300000);
|
||||
EXPECT_EQ(100000, fake_call_->GetConfig().stream_bitrates.min_bitrate_bps)
|
||||
<< "Setting max bitrate should keep previous min bitrate.";
|
||||
EXPECT_EQ(-1, fake_call_->GetConfig().stream_bitrates.start_bitrate_bps)
|
||||
<< "Setting max bitrate should not reset start bitrate.";
|
||||
EXPECT_EQ(300000, fake_call_->GetConfig().stream_bitrates.max_bitrate_bps);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetMaxSendBandwidthShouldBeRemovable) {
|
||||
channel_->SetMaxSendBandwidth(300000);
|
||||
EXPECT_EQ(300000, fake_call_->GetConfig().stream_bitrates.max_bitrate_bps);
|
||||
// <= 0 means disable (infinite) max bitrate.
|
||||
channel_->SetMaxSendBandwidth(0);
|
||||
EXPECT_EQ(-1, fake_call_->GetConfig().stream_bitrates.max_bitrate_bps)
|
||||
<< "Setting zero max bitrate did not reset start bitrate.";
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithMaxQuantization) {
|
||||
|
@ -129,9 +129,11 @@ class FakeCall : public webrtc::Call {
|
||||
|
||||
virtual webrtc::Call::Stats GetStats() const OVERRIDE;
|
||||
|
||||
virtual void SetBitrateConfig(
|
||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) OVERRIDE;
|
||||
virtual void SignalNetworkState(webrtc::Call::NetworkState state) OVERRIDE;
|
||||
|
||||
const webrtc::Call::Config config_;
|
||||
webrtc::Call::Config config_;
|
||||
webrtc::Call::NetworkState network_state_;
|
||||
std::vector<webrtc::VideoCodec> codecs_;
|
||||
std::vector<FakeVideoSendStream*> video_send_streams_;
|
||||
|
@ -65,8 +65,7 @@ class Call {
|
||||
: webrtc_config(NULL),
|
||||
send_transport(send_transport),
|
||||
voice_engine(NULL),
|
||||
overuse_callback(NULL),
|
||||
stream_start_bitrate_bps(kDefaultStartBitrateBps) {}
|
||||
overuse_callback(NULL) {}
|
||||
|
||||
static const int kDefaultStartBitrateBps;
|
||||
|
||||
@ -81,11 +80,20 @@ class Call {
|
||||
// captured frames. 'NULL' disables the callback.
|
||||
LoadObserver* overuse_callback;
|
||||
|
||||
// Start bitrate used before a valid bitrate estimate is calculated.
|
||||
// Bitrate config used until valid bitrate estimates are calculated. Also
|
||||
// used to cap total bitrate used.
|
||||
// Note: This is currently set only for video and is per-stream rather of
|
||||
// for the entire link.
|
||||
// TODO(pbos): Set start bitrate for entire Call.
|
||||
int stream_start_bitrate_bps;
|
||||
struct BitrateConfig {
|
||||
BitrateConfig()
|
||||
: min_bitrate_bps(0),
|
||||
start_bitrate_bps(kDefaultStartBitrateBps),
|
||||
max_bitrate_bps(-1) {}
|
||||
int min_bitrate_bps;
|
||||
int start_bitrate_bps;
|
||||
int max_bitrate_bps;
|
||||
} stream_bitrates;
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
@ -121,6 +129,13 @@ class Call {
|
||||
// pacing delay, etc.
|
||||
virtual Stats GetStats() const = 0;
|
||||
|
||||
// TODO(pbos): Like BitrateConfig above this is currently per-stream instead
|
||||
// of maximum for entire Call. This should be fixed along with the above.
|
||||
// Specifying a start bitrate (>0) will currently reset the current bitrate
|
||||
// estimate. This is due to how the 'x-google-start-bitrate' flag is currently
|
||||
// implemented.
|
||||
virtual void SetBitrateConfig(
|
||||
const Config::BitrateConfig& bitrate_config) = 0;
|
||||
virtual void SignalNetworkState(NetworkState state) = 0;
|
||||
|
||||
virtual ~Call() {}
|
||||
|
@ -119,6 +119,8 @@ class Call : public webrtc::Call, public PacketReceiver {
|
||||
virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
|
||||
size_t length) OVERRIDE;
|
||||
|
||||
virtual void SetBitrateConfig(
|
||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) OVERRIDE;
|
||||
virtual void SignalNetworkState(NetworkState state) OVERRIDE;
|
||||
|
||||
private:
|
||||
@ -176,6 +178,14 @@ Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
|
||||
assert(video_engine != NULL);
|
||||
assert(config.send_transport != NULL);
|
||||
|
||||
assert(config.stream_bitrates.min_bitrate_bps >= 0);
|
||||
assert(config.stream_bitrates.start_bitrate_bps >=
|
||||
config.stream_bitrates.min_bitrate_bps);
|
||||
if (config.stream_bitrates.max_bitrate_bps != -1) {
|
||||
assert(config.stream_bitrates.max_bitrate_bps >=
|
||||
config.stream_bitrates.start_bitrate_bps);
|
||||
}
|
||||
|
||||
if (config.overuse_callback) {
|
||||
overuse_observer_proxy_.reset(
|
||||
new CpuOveruseObserverProxy(config.overuse_callback));
|
||||
@ -213,15 +223,10 @@ VideoSendStream* Call::CreateVideoSendStream(
|
||||
|
||||
// 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,
|
||||
encoder_config,
|
||||
suspended_send_ssrcs_,
|
||||
base_channel_id_,
|
||||
config_.stream_start_bitrate_bps);
|
||||
VideoSendStream* send_stream = new VideoSendStream(
|
||||
config_.send_transport, overuse_observer_proxy_.get(), video_engine_,
|
||||
config, encoder_config, suspended_send_ssrcs_, base_channel_id_,
|
||||
config_.stream_bitrates);
|
||||
|
||||
// This needs to be taken before send_crit_ as both locks need to be held
|
||||
// while changing network state.
|
||||
@ -342,6 +347,30 @@ Call::Stats Call::GetStats() const {
|
||||
return stats;
|
||||
}
|
||||
|
||||
void Call::SetBitrateConfig(
|
||||
const webrtc::Call::Config::BitrateConfig& bitrate_config) {
|
||||
assert(bitrate_config.min_bitrate_bps >= 0);
|
||||
assert(bitrate_config.max_bitrate_bps == -1 ||
|
||||
bitrate_config.max_bitrate_bps > 0);
|
||||
if (config_.stream_bitrates.min_bitrate_bps ==
|
||||
bitrate_config.min_bitrate_bps &&
|
||||
(bitrate_config.start_bitrate_bps <= 0 ||
|
||||
config_.stream_bitrates.start_bitrate_bps ==
|
||||
bitrate_config.start_bitrate_bps) &&
|
||||
config_.stream_bitrates.max_bitrate_bps ==
|
||||
bitrate_config.max_bitrate_bps) {
|
||||
// Nothing new to set, early abort to avoid encoder reconfigurations.
|
||||
return;
|
||||
}
|
||||
config_.stream_bitrates = bitrate_config;
|
||||
ReadLockScoped read_lock(*send_crit_);
|
||||
for (std::map<uint32_t, VideoSendStream*>::const_iterator it =
|
||||
send_ssrcs_.begin();
|
||||
it != send_ssrcs_.end(); ++it) {
|
||||
it->second->SetBitrateConfig(bitrate_config);
|
||||
}
|
||||
}
|
||||
|
||||
void Call::SignalNetworkState(NetworkState state) {
|
||||
// Take crit for entire function, it needs to be held while updating streams
|
||||
// to guarantee a consistent state across streams.
|
||||
|
@ -640,7 +640,7 @@ TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) {
|
||||
|
||||
Call::Config GetSenderCallConfig() OVERRIDE {
|
||||
Call::Config config = EndToEndTest::GetSenderCallConfig();
|
||||
config.stream_start_bitrate_bps = kInitialBitrateKbps * 1000;
|
||||
config.stream_bitrates.start_bitrate_bps = kInitialBitrateKbps * 1000;
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -1566,7 +1566,7 @@ TEST_F(EndToEndTest, GetStats) {
|
||||
|
||||
Call::Config GetSenderCallConfig() OVERRIDE {
|
||||
Call::Config config = EndToEndTest::GetSenderCallConfig();
|
||||
config.stream_start_bitrate_bps = kStartBitrateBps;
|
||||
config.stream_bitrates.start_bitrate_bps = kStartBitrateBps;
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -123,8 +123,12 @@ void Loopback() {
|
||||
pipe_config.delay_standard_deviation_ms = flags::StdPropagationDelayMs();
|
||||
test::DirectTransport transport(pipe_config);
|
||||
Call::Config call_config(&transport);
|
||||
call_config.stream_start_bitrate_bps =
|
||||
call_config.stream_bitrates.min_bitrate_bps =
|
||||
static_cast<int>(flags::MinBitrate()) * 1000;
|
||||
call_config.stream_bitrates.start_bitrate_bps =
|
||||
static_cast<int>(flags::StartBitrate()) * 1000;
|
||||
call_config.stream_bitrates.max_bitrate_bps =
|
||||
static_cast<int>(flags::MaxBitrate()) * 1000;
|
||||
scoped_ptr<Call> call(Call::Create(call_config));
|
||||
|
||||
// Loopback, call sends to itself.
|
||||
@ -157,9 +161,9 @@ void Loopback() {
|
||||
VideoStream* stream = &encoder_config.streams[0];
|
||||
stream->width = flags::Width();
|
||||
stream->height = flags::Height();
|
||||
stream->min_bitrate_bps = static_cast<int>(flags::MinBitrate()) * 1000;
|
||||
stream->target_bitrate_bps = static_cast<int>(flags::MaxBitrate()) * 1000;
|
||||
stream->max_bitrate_bps = static_cast<int>(flags::MaxBitrate()) * 1000;
|
||||
stream->min_bitrate_bps = call_config.stream_bitrates.min_bitrate_bps;
|
||||
stream->target_bitrate_bps = call_config.stream_bitrates.max_bitrate_bps;
|
||||
stream->max_bitrate_bps = call_config.stream_bitrates.max_bitrate_bps;
|
||||
stream->max_framerate = 30;
|
||||
stream->max_qp = 56;
|
||||
|
||||
|
@ -403,7 +403,7 @@ void RampUpTest::RunRampUpTest(bool rtx,
|
||||
|
||||
Call::Config call_config(&stream_observer);
|
||||
if (start_bitrate_bps != 0) {
|
||||
call_config.stream_start_bitrate_bps = start_bitrate_bps;
|
||||
call_config.stream_bitrates.start_bitrate_bps = start_bitrate_bps;
|
||||
stream_observer.set_start_bitrate_bps(start_bitrate_bps);
|
||||
}
|
||||
|
||||
|
@ -115,20 +115,26 @@ VideoSendStream::VideoSendStream(
|
||||
const VideoEncoderConfig& encoder_config,
|
||||
const std::map<uint32_t, RtpState>& suspended_ssrcs,
|
||||
int base_channel,
|
||||
int start_bitrate_bps)
|
||||
Call::Config::BitrateConfig bitrate_config)
|
||||
: transport_adapter_(transport),
|
||||
encoded_frame_proxy_(config.post_encode_callback),
|
||||
config_(config),
|
||||
start_bitrate_bps_(start_bitrate_bps),
|
||||
bitrate_config_(bitrate_config),
|
||||
suspended_ssrcs_(suspended_ssrcs),
|
||||
external_codec_(NULL),
|
||||
channel_(-1),
|
||||
use_default_bitrate_(true),
|
||||
use_config_bitrate_(true),
|
||||
stats_proxy_(config) {
|
||||
// Duplicate assert checking of bitrate config. These should be checked in
|
||||
// Call but are added here for verbosity.
|
||||
assert(bitrate_config.min_bitrate_bps >= 0);
|
||||
assert(bitrate_config.start_bitrate_bps >= bitrate_config.min_bitrate_bps);
|
||||
if (bitrate_config.max_bitrate_bps != -1)
|
||||
assert(bitrate_config.max_bitrate_bps >= bitrate_config.start_bitrate_bps);
|
||||
|
||||
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);
|
||||
@ -385,10 +391,20 @@ bool VideoSendStream::ReconfigureVideoEncoder(
|
||||
video_codec.qpMax = std::max(video_codec.qpMax,
|
||||
static_cast<unsigned int>(streams[i].max_qp));
|
||||
}
|
||||
// Clamp bitrates to the bitrate config.
|
||||
if (video_codec.minBitrate <
|
||||
static_cast<unsigned int>(bitrate_config_.min_bitrate_bps / 1000)) {
|
||||
video_codec.minBitrate = bitrate_config_.min_bitrate_bps / 1000;
|
||||
}
|
||||
if (bitrate_config_.max_bitrate_bps != -1 &&
|
||||
video_codec.maxBitrate >
|
||||
static_cast<unsigned int>(bitrate_config_.max_bitrate_bps / 1000)) {
|
||||
video_codec.maxBitrate = bitrate_config_.max_bitrate_bps / 1000;
|
||||
}
|
||||
unsigned int start_bitrate_bps;
|
||||
if (codec_->GetCodecTargetBitrate(channel_, &start_bitrate_bps) != 0 ||
|
||||
use_default_bitrate_) {
|
||||
start_bitrate_bps = start_bitrate_bps_;
|
||||
use_config_bitrate_) {
|
||||
start_bitrate_bps = bitrate_config_.start_bitrate_bps;
|
||||
}
|
||||
video_codec.startBitrate =
|
||||
static_cast<unsigned int>(start_bitrate_bps) / 1000;
|
||||
@ -417,7 +433,8 @@ bool VideoSendStream::ReconfigureVideoEncoder(
|
||||
rtp_rtcp_->SetMinTransmitBitrate(channel_,
|
||||
config.min_transmit_bitrate_bps / 1000);
|
||||
|
||||
use_default_bitrate_ = false;
|
||||
encoder_config_ = config;
|
||||
use_config_bitrate_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -480,6 +497,19 @@ std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
|
||||
return rtp_states;
|
||||
}
|
||||
|
||||
void VideoSendStream::SetBitrateConfig(
|
||||
const Call::Config::BitrateConfig& bitrate_config) {
|
||||
int last_start_bitrate_bps = bitrate_config_.start_bitrate_bps;
|
||||
bitrate_config_ = bitrate_config;
|
||||
if (bitrate_config_.start_bitrate_bps <= 0) {
|
||||
bitrate_config_.start_bitrate_bps = last_start_bitrate_bps;
|
||||
} else {
|
||||
// Override start bitrate with bitrate from config.
|
||||
use_config_bitrate_ = true;
|
||||
}
|
||||
ReconfigureVideoEncoder(encoder_config_);
|
||||
}
|
||||
|
||||
void VideoSendStream::SignalNetworkState(Call::NetworkState state) {
|
||||
// When network goes up, enable RTCP status before setting transmission state.
|
||||
// When it goes down, disable RTCP afterwards. This ensures that any packets
|
||||
|
@ -49,7 +49,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
const VideoEncoderConfig& encoder_config,
|
||||
const std::map<uint32_t, RtpState>& suspended_ssrcs,
|
||||
int base_channel,
|
||||
int start_bitrate);
|
||||
Call::Config::BitrateConfig bitrate_config);
|
||||
|
||||
virtual ~VideoSendStream();
|
||||
|
||||
@ -72,6 +72,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
typedef std::map<uint32_t, RtpState> RtpStateMap;
|
||||
RtpStateMap GetRtpStates() const;
|
||||
|
||||
void SetBitrateConfig(const Call::Config::BitrateConfig& bitrate_config);
|
||||
void SignalNetworkState(Call::NetworkState state);
|
||||
|
||||
int GetPacerQueuingDelayMs() const;
|
||||
@ -81,7 +82,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
TransportAdapter transport_adapter_;
|
||||
EncodedFrameCallbackAdapter encoded_frame_proxy_;
|
||||
const VideoSendStream::Config config_;
|
||||
const int start_bitrate_bps_;
|
||||
VideoEncoderConfig encoder_config_;
|
||||
Call::Config::BitrateConfig bitrate_config_;
|
||||
std::map<uint32_t, RtpState> suspended_ssrcs_;
|
||||
|
||||
ViEBase* video_engine_base_;
|
||||
@ -99,7 +101,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
// Used as a workaround to indicate that we should be using the configured
|
||||
// start bitrate initially, instead of the one reported by VideoEngine (which
|
||||
// defaults to too high).
|
||||
bool use_default_bitrate_;
|
||||
bool use_config_bitrate_;
|
||||
|
||||
SendStatisticsProxy stats_proxy_;
|
||||
};
|
||||
|
@ -1583,4 +1583,102 @@ TEST_F(VideoSendStreamTest, TranslatesTwoLayerScreencastToTargetBitrate) {
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
|
||||
TEST_F(VideoSendStreamTest, UsesCallStreamBitratesAndCanReconfigureBitrates) {
|
||||
// These are chosen to be "kind of odd" to not be accidentally checked against
|
||||
// default values.
|
||||
static const int kMinBitrateKbps = 137;
|
||||
static const int kStartBitrateKbps = 345;
|
||||
static const int kLowerMaxBitrateKbps = 312;
|
||||
static const int kMaxBitrateKbps = 413;
|
||||
static const int kIncreasedStartBitrateKbps = 451;
|
||||
static const int kIncreasedMaxBitrateKbps = 597;
|
||||
class EncoderBitrateThresholdObserver : public test::SendTest,
|
||||
public test::FakeEncoder {
|
||||
public:
|
||||
EncoderBitrateThresholdObserver()
|
||||
: SendTest(kDefaultTimeoutMs),
|
||||
FakeEncoder(Clock::GetRealTimeClock()),
|
||||
num_initializations_(0) {}
|
||||
|
||||
private:
|
||||
virtual int32_t InitEncode(const VideoCodec* codecSettings,
|
||||
int32_t numberOfCores,
|
||||
size_t maxPayloadSize) OVERRIDE {
|
||||
if (num_initializations_ == 0) {
|
||||
EXPECT_EQ(static_cast<unsigned int>(kMinBitrateKbps),
|
||||
codecSettings->minBitrate);
|
||||
EXPECT_EQ(static_cast<unsigned int>(kStartBitrateKbps),
|
||||
codecSettings->startBitrate);
|
||||
EXPECT_EQ(static_cast<unsigned int>(kMaxBitrateKbps),
|
||||
codecSettings->maxBitrate);
|
||||
observation_complete_->Set();
|
||||
} else if (num_initializations_ == 1) {
|
||||
EXPECT_EQ(static_cast<unsigned int>(kLowerMaxBitrateKbps),
|
||||
codecSettings->maxBitrate);
|
||||
// The start bitrate should be kept (-1) and capped to the max bitrate.
|
||||
// Since this is not an end-to-end call no receiver should have been
|
||||
// returning a REMB that could lower this estimate.
|
||||
EXPECT_EQ(codecSettings->startBitrate, codecSettings->maxBitrate);
|
||||
} else if (num_initializations_ == 2) {
|
||||
EXPECT_EQ(static_cast<unsigned int>(kIncreasedMaxBitrateKbps),
|
||||
codecSettings->maxBitrate);
|
||||
EXPECT_EQ(static_cast<unsigned int>(kIncreasedStartBitrateKbps),
|
||||
codecSettings->startBitrate);
|
||||
}
|
||||
++num_initializations_;
|
||||
return FakeEncoder::InitEncode(codecSettings, numberOfCores,
|
||||
maxPayloadSize);
|
||||
}
|
||||
|
||||
virtual Call::Config GetSenderCallConfig() OVERRIDE {
|
||||
Call::Config config(SendTransport());
|
||||
config.stream_bitrates.min_bitrate_bps = kMinBitrateKbps * 1000;
|
||||
config.stream_bitrates.start_bitrate_bps = kStartBitrateKbps * 1000;
|
||||
config.stream_bitrates.max_bitrate_bps = kMaxBitrateKbps * 1000;
|
||||
return config;
|
||||
}
|
||||
|
||||
virtual void ModifyConfigs(
|
||||
VideoSendStream::Config* send_config,
|
||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||
VideoEncoderConfig* encoder_config) OVERRIDE {
|
||||
send_config->encoder_settings.encoder = this;
|
||||
// Set bitrates lower/higher than min/max to make sure they are properly
|
||||
// capped.
|
||||
encoder_config->streams.front().min_bitrate_bps =
|
||||
(kMinBitrateKbps - 10) * 1000;
|
||||
encoder_config->streams.front().max_bitrate_bps =
|
||||
(kIncreasedMaxBitrateKbps + 10) * 1000;
|
||||
}
|
||||
|
||||
virtual void OnCallsCreated(Call* sender_call,
|
||||
Call* receiver_call) OVERRIDE {
|
||||
call_ = sender_call;
|
||||
}
|
||||
|
||||
|
||||
virtual void PerformTest() OVERRIDE {
|
||||
EXPECT_EQ(kEventSignaled, Wait())
|
||||
<< "Timed out while waiting encoder to be configured.";
|
||||
Call::Config::BitrateConfig bitrate_config;
|
||||
bitrate_config.min_bitrate_bps = 0;
|
||||
bitrate_config.start_bitrate_bps = -1;
|
||||
bitrate_config.max_bitrate_bps = kLowerMaxBitrateKbps * 1000;
|
||||
call_->SetBitrateConfig(bitrate_config);
|
||||
EXPECT_EQ(2, num_initializations_)
|
||||
<< "Encoder should have been reconfigured with the new value.";
|
||||
bitrate_config.start_bitrate_bps = kIncreasedStartBitrateKbps * 1000;
|
||||
bitrate_config.max_bitrate_bps = kIncreasedMaxBitrateKbps * 1000;
|
||||
call_->SetBitrateConfig(bitrate_config);
|
||||
EXPECT_EQ(3, num_initializations_)
|
||||
<< "Encoder should have been reconfigured with the new value.";
|
||||
}
|
||||
|
||||
int num_initializations_;
|
||||
webrtc::Call* call_;
|
||||
} test;
|
||||
|
||||
RunBaseTest(&test);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
Loading…
Reference in New Issue
Block a user