This CL implements an alternative to the bitrate clamping that is done in BitrateControllerImpl. The default behavior is unchanged, but if the new algorithm is enabled the behavior is as follows: When the new bitrate is lower than the sum of min bitrates, the algorithm will give each observer up to its min bitrate, one observer at a time, until the bitrate budget is depleted. Thus, with this change, some observers may get less than their min bitrate, or even zero. Unit tests are implemented. Also fixing two old lint warnings in the affected files. This change is related to the auto-muter feature. BUG=2436 R=stefan@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2439005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5007 4adac7df-926f-26a2-2b94-8c16560cd09d
191 lines
6.0 KiB
C++
191 lines
6.0 KiB
C++
/*
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/video_engine/vie_channel_group.h"
|
|
|
|
#include "webrtc/common.h"
|
|
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
|
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
|
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
|
#include "webrtc/modules/utility/interface/process_thread.h"
|
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
|
#include "webrtc/video_engine/call_stats.h"
|
|
#include "webrtc/video_engine/encoder_state_feedback.h"
|
|
#include "webrtc/video_engine/vie_channel.h"
|
|
#include "webrtc/video_engine/vie_encoder.h"
|
|
#include "webrtc/video_engine/vie_remb.h"
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
|
|
class WrappingBitrateEstimator : public RemoteBitrateEstimator {
|
|
public:
|
|
WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock,
|
|
ProcessThread* process_thread)
|
|
: observer_(observer),
|
|
clock_(clock),
|
|
process_thread_(process_thread),
|
|
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
|
rbe_(RemoteBitrateEstimatorFactory().Create(observer_, clock_)),
|
|
receive_absolute_send_time_(false) {
|
|
assert(process_thread_ != NULL);
|
|
process_thread_->RegisterModule(rbe_.get());
|
|
}
|
|
virtual ~WrappingBitrateEstimator() {
|
|
process_thread_->DeRegisterModule(rbe_.get());
|
|
}
|
|
|
|
void SetReceiveAbsoluteSendTimeStatus(bool enable) {
|
|
CriticalSectionScoped cs(crit_sect_.get());
|
|
if (enable == receive_absolute_send_time_) {
|
|
return;
|
|
}
|
|
|
|
process_thread_->DeRegisterModule(rbe_.get());
|
|
if (enable) {
|
|
rbe_.reset(AbsoluteSendTimeRemoteBitrateEstimatorFactory().Create(
|
|
observer_, clock_));
|
|
} else {
|
|
rbe_.reset(RemoteBitrateEstimatorFactory().Create(observer_, clock_));
|
|
}
|
|
process_thread_->RegisterModule(rbe_.get());
|
|
|
|
receive_absolute_send_time_ = enable;
|
|
}
|
|
|
|
virtual void IncomingPacket(int64_t arrival_time_ms,
|
|
int payload_size,
|
|
const RTPHeader& header) {
|
|
CriticalSectionScoped cs(crit_sect_.get());
|
|
rbe_->IncomingPacket(arrival_time_ms, payload_size, header);
|
|
}
|
|
|
|
virtual int32_t Process() {
|
|
assert(false && "Not supposed to register the WrappingBitrateEstimator!");
|
|
return 0;
|
|
}
|
|
|
|
virtual int32_t TimeUntilNextProcess() {
|
|
assert(false && "Not supposed to register the WrappingBitrateEstimator!");
|
|
return 0;
|
|
}
|
|
|
|
virtual void OnRttUpdate(uint32_t rtt) {
|
|
CriticalSectionScoped cs(crit_sect_.get());
|
|
rbe_->OnRttUpdate(rtt);
|
|
}
|
|
|
|
virtual void RemoveStream(unsigned int ssrc) {
|
|
CriticalSectionScoped cs(crit_sect_.get());
|
|
rbe_->RemoveStream(ssrc);
|
|
}
|
|
|
|
virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
|
unsigned int* bitrate_bps) const {
|
|
CriticalSectionScoped cs(crit_sect_.get());
|
|
return rbe_->LatestEstimate(ssrcs, bitrate_bps);
|
|
}
|
|
|
|
private:
|
|
RemoteBitrateObserver* observer_;
|
|
Clock* clock_;
|
|
ProcessThread* process_thread_;
|
|
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
|
scoped_ptr<RemoteBitrateEstimator> rbe_;
|
|
bool receive_absolute_send_time_;
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator);
|
|
};
|
|
} // namespace
|
|
|
|
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
|
|
const Config& config)
|
|
: remb_(new VieRemb()),
|
|
bitrate_controller_(BitrateController::CreateBitrateController(true)),
|
|
call_stats_(new CallStats()),
|
|
remote_bitrate_estimator_(new WrappingBitrateEstimator(remb_.get(),
|
|
Clock::GetRealTimeClock(), process_thread)),
|
|
encoder_state_feedback_(new EncoderStateFeedback()),
|
|
process_thread_(process_thread) {
|
|
call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
|
|
process_thread->RegisterModule(call_stats_.get());
|
|
}
|
|
|
|
ChannelGroup::~ChannelGroup() {
|
|
call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
|
|
process_thread_->DeRegisterModule(call_stats_.get());
|
|
assert(channels_.empty());
|
|
assert(!remb_->InUse());
|
|
}
|
|
|
|
void ChannelGroup::AddChannel(int channel_id) {
|
|
channels_.insert(channel_id);
|
|
}
|
|
|
|
void ChannelGroup::RemoveChannel(int channel_id, unsigned int ssrc) {
|
|
channels_.erase(channel_id);
|
|
remote_bitrate_estimator_->RemoveStream(ssrc);
|
|
}
|
|
|
|
bool ChannelGroup::HasChannel(int channel_id) {
|
|
return channels_.find(channel_id) != channels_.end();
|
|
}
|
|
|
|
bool ChannelGroup::Empty() {
|
|
return channels_.empty();
|
|
}
|
|
|
|
BitrateController* ChannelGroup::GetBitrateController() {
|
|
return bitrate_controller_.get();
|
|
}
|
|
|
|
RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() {
|
|
return remote_bitrate_estimator_.get();
|
|
}
|
|
|
|
CallStats* ChannelGroup::GetCallStats() {
|
|
return call_stats_.get();
|
|
}
|
|
|
|
EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() {
|
|
return encoder_state_feedback_.get();
|
|
}
|
|
|
|
bool ChannelGroup::SetChannelRembStatus(int channel_id, bool sender,
|
|
bool receiver, ViEChannel* channel) {
|
|
// Update the channel state.
|
|
if (sender || receiver) {
|
|
if (!channel->EnableRemb(true)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
channel->EnableRemb(false);
|
|
}
|
|
// Update the REMB instance with necessary RTP modules.
|
|
RtpRtcp* rtp_module = channel->rtp_rtcp();
|
|
if (sender) {
|
|
remb_->AddRembSender(rtp_module);
|
|
} else {
|
|
remb_->RemoveRembSender(rtp_module);
|
|
}
|
|
if (receiver) {
|
|
remb_->AddReceiveChannel(rtp_module);
|
|
} else {
|
|
remb_->RemoveReceiveChannel(rtp_module);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ChannelGroup::SetReceiveAbsoluteSendTimeStatus(bool enable) {
|
|
static_cast<WrappingBitrateEstimator*>(remote_bitrate_estimator_.get())->
|
|
SetReceiveAbsoluteSendTimeStatus(enable);
|
|
}
|
|
} // namespace webrtc
|