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@6443 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
0a1e7e0b00
commit
eb16b811fb
@ -61,7 +61,8 @@ class Call {
|
||||
: 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 @@ class Call {
|
||||
// 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);
|
||||
|
@ -131,6 +131,8 @@ Call* Call::Create(const Call::Config& config) {
|
||||
|
||||
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 @@ VideoSendStream* Call::CreateVideoSendStream(
|
||||
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) {
|
||||
|
@ -61,6 +61,8 @@ void Loopback() {
|
||||
|
||||
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.
|
||||
|
@ -40,6 +40,7 @@ namespace webrtc {
|
||||
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 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
|
||||
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 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
|
||||
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 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
|
||||
|
||||
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 @@ class LowRateStreamObserver : public test::DirectTransport,
|
||||
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 @@ class RampUpTest : public ::testing::Test {
|
||||
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 @@ class RampUpTest : public ::testing::Test {
|
||||
|
||||
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 @@ class RampUpTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
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); }
|
||||
|
@ -114,16 +114,19 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
|
||||
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 @@ bool VideoSendStream::ReconfigureVideoEncoder(
|
||||
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;
|
||||
|
@ -44,7 +44,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
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 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
TransportAdapter transport_adapter_;
|
||||
EncodedFrameCallbackAdapter encoded_frame_proxy_;
|
||||
const VideoSendStream::Config config_;
|
||||
const int start_bitrate_bps_;
|
||||
|
||||
ViEBase* video_engine_base_;
|
||||
ViECapture* capture_;
|
||||
|
Loading…
Reference in New Issue
Block a user