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:
@@ -19,6 +19,7 @@ CallTest::CallTest()
|
||||
send_stream_(NULL),
|
||||
fake_encoder_(clock_) {
|
||||
}
|
||||
|
||||
CallTest::~CallTest() {
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user