Make ReconfigureVideoEncoder use current bitrate.

Prevents bitrate drops when changing resolution etc.

R=stefan@webrtc.org
BUG=1667

Review URL: https://webrtc-codereview.appspot.com/24069004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7493 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org
2014-10-22 12:15:24 +00:00
parent 860ccc9407
commit 32452b20b8
6 changed files with 122 additions and 5 deletions

View File

@@ -19,6 +19,7 @@ CallTest::CallTest()
send_stream_(NULL),
fake_encoder_(clock_) {
}
CallTest::~CallTest() {
}

View File

@@ -570,4 +570,92 @@ TEST_F(CallPerfTest, NoPadWithoutMinTransmitBitrate) {
TestMinTransmitBitrate(false);
}
TEST_F(CallPerfTest, KeepsHighBitrateWhenReconfiguringSender) {
static const uint32_t kInitialBitrateKbps = 400;
static const uint32_t kReconfigureThresholdKbps = 600;
static const uint32_t kPermittedReconfiguredBitrateDiffKbps = 100;
class BitrateObserver : public test::EndToEndTest, public test::FakeEncoder {
public:
BitrateObserver()
: EndToEndTest(kDefaultTimeoutMs),
FakeEncoder(Clock::GetRealTimeClock()),
time_to_reconfigure_(webrtc::EventWrapper::Create()),
encoder_inits_(0) {}
virtual int32_t InitEncode(const VideoCodec* config,
int32_t number_of_cores,
uint32_t max_payload_size) OVERRIDE {
if (encoder_inits_ == 0) {
EXPECT_EQ(kInitialBitrateKbps, config->startBitrate)
<< "Encoder not initialized at expected bitrate.";
}
++encoder_inits_;
if (encoder_inits_ == 2) {
EXPECT_GE(last_set_bitrate_, kReconfigureThresholdKbps);
EXPECT_NEAR(config->startBitrate,
last_set_bitrate_,
kPermittedReconfiguredBitrateDiffKbps)
<< "Encoder reconfigured with bitrate too far away from last set.";
observation_complete_->Set();
}
return FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
}
virtual int32_t SetRates(uint32_t new_target_bitrate_kbps,
uint32_t framerate) OVERRIDE {
last_set_bitrate_ = new_target_bitrate_kbps;
if (encoder_inits_ == 1 &&
new_target_bitrate_kbps > kReconfigureThresholdKbps) {
time_to_reconfigure_->Set();
}
return FakeEncoder::SetRates(new_target_bitrate_kbps, framerate);
}
Call::Config GetSenderCallConfig() OVERRIDE {
Call::Config config = EndToEndTest::GetSenderCallConfig();
config.stream_start_bitrate_bps = kInitialBitrateKbps * 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;
encoder_config->streams[0].min_bitrate_bps = 50000;
encoder_config->streams[0].target_bitrate_bps =
encoder_config->streams[0].max_bitrate_bps = 2000000;
encoder_config_ = *encoder_config;
}
virtual void OnStreamsCreated(
VideoSendStream* send_stream,
const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
send_stream_ = send_stream;
}
virtual void PerformTest() OVERRIDE {
ASSERT_EQ(kEventSignaled, time_to_reconfigure_->Wait(kDefaultTimeoutMs))
<< "Timed out before receiving an initial high bitrate.";
encoder_config_.streams[0].width *= 2;
encoder_config_.streams[0].height *= 2;
EXPECT_TRUE(send_stream_->ReconfigureVideoEncoder(encoder_config_));
EXPECT_EQ(kEventSignaled, Wait())
<< "Timed out while waiting for a couple of high bitrate estimates "
"after reconfiguring the send stream.";
}
private:
scoped_ptr<webrtc::EventWrapper> time_to_reconfigure_;
int encoder_inits_;
uint32_t last_set_bitrate_;
VideoSendStream* send_stream_;
VideoEncoderConfig encoder_config_;
} test;
RunBaseTest(&test);
}
} // namespace webrtc

View File

@@ -1791,6 +1791,19 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
encoder_config_.streams[i].max_bitrate_bps = 20000;
}
// Use the same total bitrates when sending a single stream to avoid lowering
// the bitrate estimate and requiring a subsequent rampup.
VideoEncoderConfig one_stream = encoder_config_;
one_stream.streams.resize(1);
for (size_t i = 1; i < encoder_config_.streams.size(); ++i) {
one_stream.streams.front().min_bitrate_bps +=
encoder_config_.streams[i].min_bitrate_bps;
one_stream.streams.front().target_bitrate_bps +=
encoder_config_.streams[i].target_bitrate_bps;
one_stream.streams.front().max_bitrate_bps +=
encoder_config_.streams[i].max_bitrate_bps;
}
CreateMatchingReceiveConfigs();
CreateStreams();
@@ -1807,8 +1820,6 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
sender_call_->DestroyVideoSendStream(send_stream_);
// Re-create VideoSendStream with only one stream.
VideoEncoderConfig one_stream = encoder_config_;
one_stream.streams.resize(1);
send_stream_ =
sender_call_->CreateVideoSendStream(send_config_, one_stream);
send_stream_->Start();

View File

@@ -154,7 +154,9 @@ bool StreamObserver::SendRtcp(const uint8_t* packet, size_t length) {
return true;
}
EventTypeWrapper StreamObserver::Wait() { return test_done_->Wait(120 * 1000); }
EventTypeWrapper StreamObserver::Wait() {
return test_done_->Wait(test::CallTest::kLongTimeoutMs);
}
void StreamObserver::ReportResult(const std::string& measurement,
size_t value,

View File

@@ -125,6 +125,7 @@ VideoSendStream::VideoSendStream(
suspended_ssrcs_(suspended_ssrcs),
external_codec_(NULL),
channel_(-1),
use_default_bitrate_(true),
stats_proxy_(config) {
video_engine_base_ = ViEBase::GetInterface(video_engine);
video_engine_base_->CreateChannel(channel_, base_channel);
@@ -378,8 +379,13 @@ bool VideoSendStream::ReconfigureVideoEncoder(
video_codec.qpMax = std::max(video_codec.qpMax,
static_cast<unsigned int>(streams[i].max_qp));
}
unsigned int start_bitrate_bps;
if (codec_->GetCodecTargetBitrate(channel_, &start_bitrate_bps) != 0 ||
use_default_bitrate_) {
start_bitrate_bps = start_bitrate_bps_;
}
video_codec.startBitrate =
static_cast<unsigned int>(start_bitrate_bps_) / 1000;
static_cast<unsigned int>(start_bitrate_bps) / 1000;
if (video_codec.minBitrate < kViEMinCodecBitrate)
video_codec.minBitrate = kViEMinCodecBitrate;
@@ -398,7 +404,11 @@ bool VideoSendStream::ReconfigureVideoEncoder(
assert(streams[0].max_framerate > 0);
video_codec.maxFramerate = streams[0].max_framerate;
return codec_->SetSendCodec(channel_, video_codec) == 0;
if (codec_->SetSendCodec(channel_, video_codec) != 0)
return false;
use_default_bitrate_ = false;
return true;
}
bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {

View File

@@ -94,6 +94,11 @@ class VideoSendStream : public webrtc::VideoSendStream,
int channel_;
int capture_id_;
// 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_;
SendStatisticsProxy stats_proxy_;
};
} // namespace internal