Refactoring the receive-side bandwidth estimation into its own module.

Each REMB group has one remote_bitrate_estimator object. For now the
estimator keeps one estimate for every SSRC. In a later commit this will
be unified and one estimate will be used for all SSRC in one group.

BUG=
TEST=

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2363 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2012-06-05 10:44:00 +00:00
parent d2acea6b30
commit f72881406f
41 changed files with 946 additions and 415 deletions

View File

@ -28,6 +28,7 @@
'audio_processing/utility/util.gypi',
'bitrate_controller/bitrate_controller.gypi',
'media_file/source/media_file.gypi',
'remote_bitrate_estimator/remote_bitrate_estimator.gypi',
'udp_transport/source/udp_transport.gypi',
'utility/source/utility.gypi',
'video_coding/codecs/i420/main/source/i420.gypi',
@ -47,7 +48,6 @@
'audio_coding/codecs/iSAC/isacfix_test.gypi',
'audio_processing/apm_tests.gypi',
'rtp_rtcp/source/rtp_rtcp_tests.gypi',
'rtp_rtcp/test/test_bwe/test_bwe.gypi',
'rtp_rtcp/test/testFec/test_fec.gypi',
'rtp_rtcp/test/testAPI/test_api.gypi',
'video_coding/main/source/video_coding_test.gypi',

View File

@ -0,0 +1,5 @@
pwestin@webrtc.org
stefan@webrtc.org
henrik.lundin@webrtc.org
mflodman@webrtc.org
asapersson@webrtc.org

View File

@ -0,0 +1,91 @@
/*
* 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 "bitrate_estimator.h"
namespace webrtc {
enum { kBitrateAverageWindow = 2000 };
BitRateStats::BitRateStats()
:_dataSamples(), _accumulatedBytes(0)
{
}
BitRateStats::~BitRateStats()
{
while (_dataSamples.size() > 0)
{
delete _dataSamples.front();
_dataSamples.pop_front();
}
}
void BitRateStats::Init()
{
_accumulatedBytes = 0;
while (_dataSamples.size() > 0)
{
delete _dataSamples.front();
_dataSamples.pop_front();
}
}
void BitRateStats::Update(WebRtc_UWord32 packetSizeBytes, WebRtc_Word64 nowMs)
{
// Find an empty slot for storing the new sample and at the same time
// accumulate the history.
_dataSamples.push_back(new DataTimeSizeTuple(packetSizeBytes, nowMs));
_accumulatedBytes += packetSizeBytes;
EraseOld(nowMs);
}
void BitRateStats::EraseOld(WebRtc_Word64 nowMs)
{
while (_dataSamples.size() > 0)
{
if (nowMs - _dataSamples.front()->_timeCompleteMs >
kBitrateAverageWindow)
{
// Delete old sample
_accumulatedBytes -= _dataSamples.front()->_sizeBytes;
delete _dataSamples.front();
_dataSamples.pop_front();
}
else
{
break;
}
}
}
WebRtc_UWord32 BitRateStats::BitRate(WebRtc_Word64 nowMs)
{
// Calculate the average bit rate the past BITRATE_AVERAGE_WINDOW ms.
// Removes any old samples from the list.
EraseOld(nowMs);
WebRtc_Word64 timeOldest = nowMs;
if (_dataSamples.size() > 0)
{
timeOldest = _dataSamples.front()->_timeCompleteMs;
}
// Update average bit rate
float denom = static_cast<float>(nowMs - timeOldest);
if (nowMs == timeOldest)
{
// Calculate with a one second window when we haven't
// received more than one packet.
denom = 1000.0;
}
return static_cast<WebRtc_UWord32>(_accumulatedBytes * 8.0f * 1000.0f /
denom + 0.5f);
}
} // namespace webrtc

View File

@ -0,0 +1,50 @@
/*
* 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.
*/
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_
#include <list>
#include "typedefs.h"
namespace webrtc {
class BitRateStats
{
public:
BitRateStats();
~BitRateStats();
void Init();
void Update(WebRtc_UWord32 packetSizeBytes, WebRtc_Word64 nowMs);
WebRtc_UWord32 BitRate(WebRtc_Word64 nowMs);
private:
struct DataTimeSizeTuple
{
DataTimeSizeTuple(uint32_t sizeBytes, int64_t timeCompleteMs)
:
_sizeBytes(sizeBytes),
_timeCompleteMs(timeCompleteMs) {}
WebRtc_UWord32 _sizeBytes;
WebRtc_Word64 _timeCompleteMs;
};
void EraseOld(WebRtc_Word64 nowMs);
std::list<DataTimeSizeTuple*> _dataSamples;
WebRtc_UWord32 _accumulatedBytes;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_BITRATE_ESTIMATOR_H_

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* 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
@ -8,15 +8,14 @@
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* This file includes unit tests for the bandwidth estimation and management
* This file includes unit tests for the bitrate estimator.
*/
#include <gtest/gtest.h>
#include "typedefs.h"
#include "Bitrate.h"
#include "bitrate_estimator.h"
namespace {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* 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
@ -43,9 +43,10 @@ class RateControlInput
public:
RateControlInput(BandwidthUsage bwState,
WebRtc_UWord32 incomingBitRate,
double noiseVar) :
_bwState(bwState), _incomingBitRate(incomingBitRate), _noiseVar(noiseVar)
{};
double noiseVar)
: _bwState(bwState),
_incomingBitRate(incomingBitRate),
_noiseVar(noiseVar) {}
BandwidthUsage _bwState;
WebRtc_UWord32 _incomingBitRate;

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_
#include <gmock/gmock.h>
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
namespace webrtc {
class MockRemoteBitrateObserver : public RemoteBitrateObserver {
public:
MOCK_METHOD2(OnReceiveBitrateChanged,
void(unsigned int ssrc, unsigned int bitrate));
};
} // namespace webrtc
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_REMOTE_BITRATE_ESTIMATOR_H_

View File

@ -0,0 +1,82 @@
/*
* 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.
*/
// RemoteBitrateEstimator
// This class estimates the incoming bitrate capacity.
#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_REMOTE_BITRATE_ESTIMATOR_H_
#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_REMOTE_BITRATE_ESTIMATOR_H_
#include <map>
#include "modules/remote_bitrate_estimator/bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/overuse_detector.h"
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/scoped_ptr.h"
#include "typedefs.h"
namespace webrtc {
// RemoteBitrateObserver is used to signal changes in bitrate estimates for
// the incoming stream.
class RemoteBitrateObserver {
public:
// Called when a receive channel has a new bitrate estimate for the incoming
// stream.
virtual void OnReceiveBitrateChanged(unsigned int ssrc,
unsigned int bitrate) = 0;
virtual ~RemoteBitrateObserver() {}
};
class RemoteBitrateEstimator {
public:
explicit RemoteBitrateEstimator(RemoteBitrateObserver* observer);
// Called for each incoming packet. If this is a new SSRC, a new
// BitrateControl will be created.
void IncomingPacket(unsigned int ssrc,
int packet_size,
int64_t arrival_time,
uint32_t rtp_timestamp,
int64_t packet_send_time);
// Triggers a new estimate calculation for the stream identified by |ssrc|.
void UpdateEstimate(unsigned int ssrc, int64_t time_now);
// Set the current round-trip time experienced by the stream identified by
// |ssrc|.
void SetRtt(unsigned int ssrc);
// Removes all data for |ssrc|.
void RemoveStream(unsigned int ssrc);
// Returns true if a valid estimate exists for a stream identified by |ssrc|
// and sets |bitrate_bps| to the estimated bitrate in bits per second.
bool LatestEstimate(unsigned int ssrc, unsigned int* bitrate_bps) const;
private:
struct BitrateControls {
RemoteRateControl remote_rate;
OverUseDetector overuse_detector;
BitRateStats incoming_bitrate;
};
typedef std::map<unsigned int, BitrateControls> SsrcBitrateControlsMap;
SsrcBitrateControlsMap bitrate_controls_;
RemoteBitrateObserver* observer_;
scoped_ptr<CriticalSectionWrapper> crit_sect_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_REMOTE_BITRATE_ESTIMATOR_H_

View File

@ -14,8 +14,8 @@
#include <windows.h>
#endif
#include "modules/rtp_rtcp/source/overuse_detector.h"
#include "modules/rtp_rtcp/source/remote_rate_control.h"
#include "modules/remote_bitrate_estimator/overuse_detector.h"
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "system_wrappers/interface/trace.h"
@ -109,8 +109,8 @@ void OverUseDetector::Reset() {
tsDeltaHist_.clear();
}
bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader,
const WebRtc_UWord16 packetSize,
void OverUseDetector::Update(WebRtc_UWord16 packetSize,
WebRtc_UWord32 timestamp,
const WebRtc_Word64 nowMS) {
#ifdef WEBRTC_BWE_MATLAB
// Create plots
@ -145,14 +145,14 @@ bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader,
bool wrapped = false;
bool completeFrame = false;
if (currentFrame_.timestamp_ == -1) {
currentFrame_.timestamp_ = rtpHeader.header.timestamp;
} else if (ModuleRTPUtility::OldTimestamp(
rtpHeader.header.timestamp,
currentFrame_.timestamp_ = timestamp;
} else if (OldTimestamp(
timestamp,
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
&wrapped)) {
// Don't update with old data
return completeFrame;
} else if (rtpHeader.header.timestamp != currentFrame_.timestamp_) {
return;
} else if (timestamp != currentFrame_.timestamp_) {
// First packet of a later frame, the previous frame sample is ready
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
"Frame complete at %I64i", currentFrame_.completeTimeMs_);
@ -160,7 +160,7 @@ bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader,
WebRtc_Word64 tDelta = 0;
double tsDelta = 0;
// Check for wrap
ModuleRTPUtility::OldTimestamp(
OldTimestamp(
static_cast<WebRtc_UWord32>(prevFrame_.timestamp_),
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
&wrapped);
@ -172,7 +172,7 @@ bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader,
// The new timestamp is now the current frame,
// and the old timestamp becomes the previous frame.
prevFrame_ = currentFrame_;
currentFrame_.timestamp_ = rtpHeader.header.timestamp;
currentFrame_.timestamp_ = timestamp;
currentFrame_.size_ = 0;
currentFrame_.completeTimeMs_ = -1;
completeFrame = true;
@ -180,7 +180,6 @@ bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader,
// Accumulate the frame size
currentFrame_.size_ += packetSize;
currentFrame_.completeTimeMs_ = nowMS;
return completeFrame;
}
BandwidthUsage OverUseDetector::State() const {
@ -420,4 +419,22 @@ BandwidthUsage OverUseDetector::Detect(double tsDelta) {
return hypothesis_;
}
bool OverUseDetector::OldTimestamp(uint32_t newTimestamp,
uint32_t existingTimestamp,
bool* wrapped) {
bool tmpWrapped =
(newTimestamp < 0x0000ffff && existingTimestamp > 0xffff0000) ||
(newTimestamp > 0xffff0000 && existingTimestamp < 0x0000ffff);
*wrapped = tmpWrapped;
if (existingTimestamp > newTimestamp && !tmpWrapped) {
return true;
} else if (existingTimestamp <= newTimestamp && !tmpWrapped) {
return false;
} else if (existingTimestamp < newTimestamp && tmpWrapped) {
return true;
} else {
return false;
}
}
} // namespace webrtc

View File

@ -13,7 +13,7 @@
#include <list>
#include "modules/interface/module_common_types.h"
#include "modules/rtp_rtcp/source/bwe_defines.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "typedefs.h" // NOLINT(build/include)
#ifdef WEBRTC_BWE_MATLAB
@ -27,8 +27,8 @@ class OverUseDetector {
public:
OverUseDetector();
~OverUseDetector();
bool Update(const WebRtcRTPHeader& rtpHeader,
const WebRtc_UWord16 packetSize,
void Update(const WebRtc_UWord16 packetSize,
const WebRtc_UWord32 timestamp,
const WebRtc_Word64 nowMS);
BandwidthUsage State() const;
void Reset();
@ -44,6 +44,10 @@ class OverUseDetector {
WebRtc_Word64 timestamp_;
};
static bool OldTimestamp(uint32_t newTimestamp,
uint32_t existingTimestamp,
bool* wrapped);
void CompensatedTimeDelta(const FrameSample& currentFrame,
const FrameSample& prevFrame,
WebRtc_Word64& tDelta,

View File

@ -0,0 +1,102 @@
/*
* 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 "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "system_wrappers/interface/tick_util.h"
namespace webrtc {
RemoteBitrateEstimator::RemoteBitrateEstimator(
RemoteBitrateObserver* observer)
: observer_(observer),
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
assert(observer_);
}
void RemoteBitrateEstimator::IncomingPacket(unsigned int ssrc,
int packet_size,
int64_t arrival_time,
uint32_t rtp_timestamp,
int64_t packet_send_time) {
CriticalSectionScoped cs(crit_sect_.get());
SsrcBitrateControlsMap::iterator it = bitrate_controls_.find(ssrc);
if (it == bitrate_controls_.end()) {
// This is a new SSRC. Adding to map.
// TODO(holmer): If the channel changes SSRC the old SSRC will still be
// around in this map until the channel is deleted. This is OK since the
// callback will no longer be called for the old SSRC. This will be
// automatically cleaned up when we have one RemoteBitrateEstimator per REMB
// group.
bitrate_controls_[ssrc] = BitrateControls();
it = bitrate_controls_.find(ssrc);
}
OverUseDetector* overuse_detector =
&bitrate_controls_[ssrc].overuse_detector;
bitrate_controls_[ssrc].incoming_bitrate.Update(packet_size, arrival_time);
const BandwidthUsage prior_state = overuse_detector->State();
overuse_detector->Update(packet_size, rtp_timestamp, arrival_time);
if (prior_state != overuse_detector->State() &&
overuse_detector->State() == kBwOverusing) {
// The first overuse should immediately trigger a new estimate.
UpdateEstimate(ssrc, arrival_time);
}
}
void RemoteBitrateEstimator::UpdateEstimate(unsigned int ssrc,
int64_t time_now) {
CriticalSectionScoped cs(crit_sect_.get());
SsrcBitrateControlsMap::iterator it = bitrate_controls_.find(ssrc);
if (it == bitrate_controls_.end()) {
return;
}
OverUseDetector* overuse_detector = &it->second.overuse_detector;
RemoteRateControl* remote_rate = &it->second.remote_rate;
const RateControlInput input(overuse_detector->State(),
it->second.incoming_bitrate.BitRate(time_now),
overuse_detector->NoiseVar());
const RateControlRegion region = remote_rate->Update(&input, time_now);
unsigned int target_bitrate = remote_rate->UpdateBandwidthEstimate(time_now);
if (remote_rate->ValidEstimate()) {
observer_->OnReceiveBitrateChanged(ssrc, target_bitrate);
}
overuse_detector->SetRateControlRegion(region);
}
void RemoteBitrateEstimator::SetRtt(unsigned int rtt) {
CriticalSectionScoped cs(crit_sect_.get());
for (SsrcBitrateControlsMap::iterator it = bitrate_controls_.begin();
it != bitrate_controls_.end(); ++it) {
it->second.remote_rate.SetRtt(rtt);
}
}
void RemoteBitrateEstimator::RemoveStream(unsigned int ssrc) {
CriticalSectionScoped cs(crit_sect_.get());
// Ignoring the return value which is the number of elements erased.
bitrate_controls_.erase(ssrc);
}
bool RemoteBitrateEstimator::LatestEstimate(unsigned int ssrc,
unsigned int* bitrate_bps) const {
CriticalSectionScoped cs(crit_sect_.get());
assert(bitrate_bps != NULL);
SsrcBitrateControlsMap::const_iterator it = bitrate_controls_.find(ssrc);
if (it == bitrate_controls_.end()) {
return false;
}
if (!it->second.remote_rate.ValidEstimate()) {
return false;
}
*bitrate_bps = it->second.remote_rate.LatestEstimate();
return true;
}
} // namespace webrtc

View File

@ -0,0 +1,71 @@
# Copyright (c) 2011 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.
{
'targets': [
{
'target_name': 'remote_bitrate_estimator',
'type': '<(library)',
'dependencies': [
# system_wrappers
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'include_dirs': [
'include',
'../rtp_rtcp/interface',
'../interface',
],
'direct_dependent_settings': {
'include_dirs': [
'include',
],
},
'sources': [
# interface
'include/bwe_defines.h',
'include/remote_bitrate_estimator.h',
# source
'bitrate_estimator.cc',
'bitrate_estimator.h',
'overuse_detector.cc',
'overuse_detector.h',
'remote_bitrate_estimator.cc',
'remote_rate_control.cc',
'remote_rate_control.h',
], # source
},
], # targets
'conditions': [
['include_tests==1', {
'targets': [
{
'target_name': 'remote_bitrate_estimator_unittests',
'type': 'executable',
'dependencies': [
'remote_bitrate_estimator',
'<(webrtc_root)/../testing/gmock.gyp:gmock',
'<(webrtc_root)/../testing/gtest.gyp:gtest',
'<(webrtc_root)/../test/test.gyp:test_support_main',
],
'sources': [
'include/mock/mock_remote_bitrate_estimator.h',
'bitrate_estimator_unittest.cc',
'remote_bitrate_estimator_unittest.cc',
],
},
], # targets
}], # build_with_chromium
], # conditions
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

View File

@ -0,0 +1,297 @@
/*
* 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.
*/
// This file includes unit tests for RemoteBitrateEstimator.
#include <gtest/gtest.h>
#include <list>
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
enum { kMtu = 1200 };
class TestBitrateObserver : public RemoteBitrateObserver {
public:
TestBitrateObserver() : updated_(false), latest_bitrate_(0) {}
void OnReceiveBitrateChanged(unsigned int ssrc, unsigned int bitrate) {
latest_bitrate_ = bitrate;
updated_ = true;
}
bool updated() {
bool updated = updated_;
updated_ = false;
return updated;
}
unsigned int latest_bitrate() const {
return latest_bitrate_;
}
private:
bool updated_;
unsigned int latest_bitrate_;
};
class StreamGenerator {
public:
struct Packet {
int64_t send_time;
int64_t arrival_time;
uint32_t rtp_timestamp;
unsigned int size;
};
typedef std::list<Packet*> PacketList;
StreamGenerator(int fps, int bitrate_bps, int capacity, int64_t time_now)
: fps_(fps),
bitrate_bps_(bitrate_bps),
capacity_(capacity),
time_now_(time_now),
prev_arrival_time_(time_now),
rtp_timestamp_offset_(0xFFFFF000) {}
void SetCapacity(int capacity_bps) {
ASSERT_GT(capacity_bps, 0);
capacity_ = capacity_bps;
}
void SetBitrate(int bitrate_bps) {
ASSERT_GE(bitrate_bps, 0);
bitrate_bps_ = bitrate_bps;
}
void SetRtpTimestampOffset(uint32_t offset) {
rtp_timestamp_offset_ = offset;
}
void GenerateFrame(PacketList* packets) {
ASSERT_FALSE(packets == NULL);
ASSERT_TRUE(packets->empty());
ASSERT_GT(fps_, 0);
int bits_per_frame = bitrate_bps_ / fps_;
int n_packets = std::max(bits_per_frame / (8 * kMtu), 1);
int packet_size = bits_per_frame / (8 * n_packets);
ASSERT_GE(n_packets, 0);
for (int i = 0; i < n_packets; ++i) {
Packet* packet = new Packet;
packet->send_time = time_now_ + kSendSideOffsetMs;
ASSERT_GT(capacity_, 0);
packet->arrival_time = std::max(
prev_arrival_time_ + 8 * 1000 * packet_size / capacity_,
time_now_);
packet->size = packet_size;
packet->rtp_timestamp = rtp_timestamp_offset_ + 90 * packet->send_time;
prev_arrival_time_ = packet->arrival_time;
packets->push_back(packet);
}
time_now_ = time_now_ + 1000 / fps_;
}
int64_t TimeNow() const {
return time_now_;
}
private:
enum { kSendSideOffsetMs = 1000 };
int fps_;
int bitrate_bps_;
int capacity_;
int64_t time_now_;
int64_t prev_arrival_time_;
uint32_t rtp_timestamp_offset_;
};
class RemoteBitrateEstimatorTest : public ::testing::Test {
protected:
virtual void SetUp() {
bitrate_observer_.reset(new TestBitrateObserver);
bitrate_estimator_.reset(new RemoteBitrateEstimator(
bitrate_observer_.get()));
// Framerate: 30 fps; Start bitrate: 300 kbps; Link capacity: 1000 kbps,
// Start time: 0.
stream_generator_.reset(new StreamGenerator(30, 3e5, 1e6, 0));
}
// Generates a frame of packets belonging to a stream at a given bitrate and
// with a given ssrc. The stream is pushed through a very simple simulated
// network, and is then given to the receive-side bandwidth estimator.
void GenerateAndProcessFrame(unsigned int ssrc, unsigned int bitrate_bps) {
stream_generator_->SetBitrate(bitrate_bps);
StreamGenerator::PacketList packets;
stream_generator_->GenerateFrame(&packets);
int64_t last_arrival_time = -1;
bool prev_was_decrease = false;
while (!packets.empty()) {
StreamGenerator::Packet* packet = packets.front();
bitrate_estimator_->IncomingPacket(ssrc,
packet->size,
packet->arrival_time,
packet->rtp_timestamp,
-1);
if (bitrate_observer_->updated()) {
// Verify that new estimates only are triggered by an overuse and a
// rate decrease.
EXPECT_LE(bitrate_observer_->latest_bitrate(), bitrate_bps);
EXPECT_FALSE(prev_was_decrease);
prev_was_decrease = true;
} else {
prev_was_decrease = false;
}
last_arrival_time = packet->arrival_time;
delete packet;
packets.pop_front();
}
EXPECT_GT(last_arrival_time, -1);
bitrate_estimator_->UpdateEstimate(ssrc, last_arrival_time);
}
// Run the bandwidth estimator with a stream of |number_of_frames| frames.
// Can for instance be used to run the estimator for some time to get it
// into a steady state.
unsigned int SteadyStateRun(unsigned int ssrc,
int number_of_frames,
unsigned int start_bitrate,
unsigned int min_bitrate,
unsigned int max_bitrate) {
unsigned int bitrate_bps = start_bitrate;
bool bitrate_update_seen = false;
// Produce |number_of_frames| frames and give them to the estimator.
for (int i = 0; i < number_of_frames; ++i) {
GenerateAndProcessFrame(ssrc, bitrate_bps);
if (bitrate_observer_->updated()) {
EXPECT_LT(bitrate_observer_->latest_bitrate(), max_bitrate);
EXPECT_GT(bitrate_observer_->latest_bitrate(), min_bitrate);
bitrate_bps = bitrate_observer_->latest_bitrate();
bitrate_update_seen = true;
}
}
EXPECT_TRUE(bitrate_update_seen);
return bitrate_bps;
}
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
scoped_ptr<TestBitrateObserver> bitrate_observer_;
scoped_ptr<StreamGenerator> stream_generator_;
};
TEST_F(RemoteBitrateEstimatorTest, TestInitialBehavior) {
unsigned int bitrate_bps = 0;
unsigned int ssrc = 0;
int64_t time_now = 0;
uint32_t timestamp = 0;
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(ssrc, &bitrate_bps));
bitrate_estimator_->UpdateEstimate(ssrc, time_now);
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(ssrc, &bitrate_bps));
EXPECT_FALSE(bitrate_observer_->updated());
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
bitrate_estimator_->IncomingPacket(ssrc, kMtu, time_now,
timestamp, -1);
bitrate_estimator_->UpdateEstimate(ssrc, time_now);
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(ssrc, &bitrate_bps));
EXPECT_FALSE(bitrate_observer_->updated());
// Waiting more than one second gives us a valid estimate.
time_now += 1001;
bitrate_estimator_->UpdateEstimate(ssrc, time_now);
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(ssrc, &bitrate_bps));
EXPECT_EQ(bitrate_bps, 10734u);
EXPECT_TRUE(bitrate_observer_->updated());
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
}
// Make sure we initially increase the bitrate as expected.
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseRtpTimestamps) {
const int kExpectedIterations = 323;
unsigned int bitrate_bps = 30000;
unsigned int ssrc = 0;
int iterations = 0;
// Feed the estimator with a stream of packets and verify that it reaches
// 500 kbps at the expected time.
while (bitrate_bps < 5e5) {
GenerateAndProcessFrame(ssrc, bitrate_bps);
if (bitrate_observer_->updated()) {
EXPECT_GT(bitrate_observer_->latest_bitrate(), bitrate_bps);
bitrate_bps = bitrate_observer_->latest_bitrate();
}
++iterations;
ASSERT_LE(iterations, kExpectedIterations);
}
ASSERT_EQ(iterations, kExpectedIterations);
}
// Verify that the time it takes for the estimator to reduce the bitrate when
// the capacity is tightened stays the same.
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestamps) {
const unsigned int kSsrc = 0;
const int kNumberOfFrames= 1000;
const int kStartBitrate = 900e3;
const int kMinExpectedBitrate = 800e3;
const int kMaxExpectedBitrate = 1500e3;
// Run in steady state to make the estimator converge.
unsigned int bitrate_bps = SteadyStateRun(kSsrc, kNumberOfFrames,
kStartBitrate, kMinExpectedBitrate,
kMaxExpectedBitrate);
// Reduce the capacity and verify the decrease time.
stream_generator_->SetCapacity(500e3);
int64_t bitrate_drop_time = 0;
for (int i = 0; i < 1000; ++i) {
GenerateAndProcessFrame(kSsrc, bitrate_bps);
if (bitrate_observer_->updated()) {
if (bitrate_observer_->latest_bitrate() <= 500e3) {
bitrate_drop_time = stream_generator_->TimeNow();
}
bitrate_bps = bitrate_observer_->latest_bitrate();
}
}
EXPECT_EQ(66000, bitrate_drop_time);
}
// Verify that the time it takes for the estimator to reduce the bitrate when
// the capacity is tightened stays the same. This test also verifies that we
// handle wrap-arounds in this scenario.
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestampsWrap) {
const unsigned int kSsrc = 0;
const int kFramerate= 30;
const int kStartBitrate = 900e3;
const int kMinExpectedBitrate = 800e3;
const int kMaxExpectedBitrate = 1500e3;
const int kSteadyStateTime = 5; // Seconds.
// Trigger wrap right after the steady state run.
stream_generator_->SetRtpTimestampOffset(
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
// Run in steady state to make the estimator converge.
unsigned int bitrate_bps = SteadyStateRun(kSsrc,
kSteadyStateTime * kFramerate,
kStartBitrate,
kMinExpectedBitrate,
kMaxExpectedBitrate);
// Reduce the capacity and verify the decrease time.
stream_generator_->SetCapacity(500e3);
int64_t bitrate_drop_time = 0;
for (int i = 0; i < 1000; ++i) {
GenerateAndProcessFrame(kSsrc, bitrate_bps);
if (bitrate_observer_->updated()) {
if (bitrate_observer_->latest_bitrate() <= 500e3) {
bitrate_drop_time = stream_generator_->TimeNow();
}
bitrate_bps = bitrate_observer_->latest_bitrate();
}
}
EXPECT_EQ(37356, bitrate_drop_time);
}
} // namespace webrtc

View File

@ -8,14 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
#include <assert.h>
#include <math.h>
#include <string.h>
#if _WIN32
#include <windows.h>
#endif
#include "remote_rate_control.h"
#include "trace.h"
#include <math.h>
#include <string.h>
#include "system_wrappers/interface/trace.h"
#ifdef MATLAB
extern MatlabEngine eng; // global variable defined elsewhere
@ -40,7 +42,8 @@ _timeFirstIncomingEstimate(-1),
_initializedBitRate(false),
_avgChangePeriod(1000.0f),
_lastChangeMs(-1),
_beta(0.9f)
_beta(0.9f),
_rtt(0)
#ifdef MATLAB
,_plot1(NULL),
_plot2(NULL)
@ -83,7 +86,8 @@ bool RemoteRateControl::ValidEstimate() const {
return _initializedBitRate;
}
WebRtc_Word32 RemoteRateControl::SetConfiguredBitRates(WebRtc_UWord32 minBitRateBps, WebRtc_UWord32 maxBitRateBps)
WebRtc_Word32 RemoteRateControl::SetConfiguredBitRates(
WebRtc_UWord32 minBitRateBps, WebRtc_UWord32 maxBitRateBps)
{
if (minBitRateBps > maxBitRateBps)
{
@ -91,7 +95,8 @@ WebRtc_Word32 RemoteRateControl::SetConfiguredBitRates(WebRtc_UWord32 minBitRate
}
_minConfiguredBitRate = minBitRateBps;
_maxConfiguredBitRate = maxBitRateBps;
_currentBitRate = BWE_MIN(BWE_MAX(minBitRateBps, _currentBitRate), maxBitRateBps);
_currentBitRate = BWE_MIN(BWE_MAX(minBitRateBps, _currentBitRate),
maxBitRateBps);
return 0;
}
@ -99,18 +104,23 @@ WebRtc_UWord32 RemoteRateControl::LatestEstimate() const {
return _currentBitRate;
}
WebRtc_UWord32 RemoteRateControl::UpdateBandwidthEstimate(WebRtc_UWord32 RTT,
WebRtc_Word64 nowMS)
WebRtc_UWord32 RemoteRateControl::UpdateBandwidthEstimate(WebRtc_Word64 nowMS)
{
_currentBitRate = ChangeBitRate(_currentBitRate, _currentInput._incomingBitRate,
_currentInput._noiseVar, RTT, nowMS);
_currentBitRate = ChangeBitRate(_currentBitRate,
_currentInput._incomingBitRate,
_currentInput._noiseVar,
nowMS);
return _currentBitRate;
}
RateControlRegion RemoteRateControl::Update(const RateControlInput& input,
bool& firstOverUse,
void RemoteRateControl::SetRtt(unsigned int rtt) {
_rtt = rtt;
}
RateControlRegion RemoteRateControl::Update(const RateControlInput* input,
WebRtc_Word64 nowMS)
{
assert(input);
#ifdef MATLAB
// Create plots
if (_plot1 == NULL)
@ -133,23 +143,20 @@ RateControlRegion RemoteRateControl::Update(const RateControlInput& input,
}
#endif
firstOverUse = (_currentInput._bwState != kBwOverusing &&
input._bwState == kBwOverusing);
// Set the initial bit rate value to what we're receiving the first second
if (!_initializedBitRate)
{
if (_timeFirstIncomingEstimate < 0)
{
if (input._incomingBitRate > 0)
if (input->_incomingBitRate > 0)
{
_timeFirstIncomingEstimate = nowMS;
}
}
else if (nowMS - _timeFirstIncomingEstimate > 1000 &&
input._incomingBitRate > 0)
input->_incomingBitRate > 0)
{
_currentBitRate = input._incomingBitRate;
_currentBitRate = input->_incomingBitRate;
_initializedBitRate = true;
}
}
@ -157,20 +164,19 @@ RateControlRegion RemoteRateControl::Update(const RateControlInput& input,
if (_updated && _currentInput._bwState == kBwOverusing)
{
// Only update delay factor and incoming bit rate. We always want to react on an over-use.
_currentInput._noiseVar = input._noiseVar;
_currentInput._incomingBitRate = input._incomingBitRate;
_currentInput._noiseVar = input->_noiseVar;
_currentInput._incomingBitRate = input->_incomingBitRate;
return _rcRegion;
}
_updated = true;
_currentInput = input;
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Incoming rate = %u kbps", input._incomingBitRate/1000);
_currentInput = *input;
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Incoming rate = %u kbps", input->_incomingBitRate/1000);
return _rcRegion;
}
WebRtc_UWord32 RemoteRateControl::ChangeBitRate(WebRtc_UWord32 currentBitRate,
WebRtc_UWord32 incomingBitRate,
double noiseVar,
WebRtc_UWord32 RTT,
WebRtc_Word64 nowMS)
{
if (!_updated)
@ -209,13 +215,13 @@ WebRtc_UWord32 RemoteRateControl::ChangeBitRate(WebRtc_UWord32 currentBitRate,
}
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
"BWE: Response time: %f + %i + 10*33\n",
_avgChangePeriod, RTT);
const WebRtc_UWord32 responseTime = static_cast<WebRtc_UWord32>(_avgChangePeriod + 0.5f) + RTT + 300;
_avgChangePeriod, _rtt);
const WebRtc_UWord32 responseTime = static_cast<WebRtc_UWord32>(_avgChangePeriod + 0.5f) + _rtt + 300;
double alpha = RateIncreaseFactor(nowMS, _lastBitRateChange,
responseTime, noiseVar);
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
"BWE: _avgChangePeriod = %f ms; RTT = %u ms", _avgChangePeriod, RTT);
"BWE: _avgChangePeriod = %f ms; RTT = %u ms", _avgChangePeriod, _rtt);
currentBitRate = static_cast<WebRtc_UWord32>(currentBitRate * alpha) + 1000;
if (_maxHoldRate > 0 && _beta * _maxHoldRate > currentBitRate)

View File

@ -11,7 +11,7 @@
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_REMOTE_RATE_CONTROL_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_REMOTE_RATE_CONTROL_H_
#include "bwe_defines.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "typedefs.h"
#ifdef MATLAB
@ -27,9 +27,9 @@ public:
WebRtc_Word32 SetConfiguredBitRates(WebRtc_UWord32 minBitRate,
WebRtc_UWord32 maxBitRate);
WebRtc_UWord32 LatestEstimate() const;
WebRtc_UWord32 UpdateBandwidthEstimate(WebRtc_UWord32 RTT,
WebRtc_Word64 nowMS);
RateControlRegion Update(const RateControlInput& input, bool& firstOverUse,
WebRtc_UWord32 UpdateBandwidthEstimate(WebRtc_Word64 nowMS);
void SetRtt(unsigned int rtt);
RateControlRegion Update(const RateControlInput* input,
WebRtc_Word64 nowMS);
void Reset();
@ -40,7 +40,7 @@ public:
private:
WebRtc_UWord32 ChangeBitRate(WebRtc_UWord32 currentBitRate,
WebRtc_UWord32 incomingBitRate,
double delayFactor, WebRtc_UWord32 RTT,
double delayFactor,
WebRtc_Word64 nowMS);
double RateIncreaseFactor(WebRtc_Word64 nowMs,
WebRtc_Word64 lastMs,
@ -72,6 +72,7 @@ private:
float _avgChangePeriod;
WebRtc_Word64 _lastChangeMs;
float _beta;
unsigned int _rtt;
#ifdef MATLAB
MatlabPlot *_plot1;
MatlabPlot *_plot2;

View File

@ -18,6 +18,8 @@
namespace webrtc {
// forward declaration
class RemoteBitrateEstimator;
class RemoteBitrateObserver;
class Transport;
class RtpRtcp : public Module {
@ -35,7 +37,7 @@ class RtpRtcp : public Module {
intra_frame_callback(NULL),
bandwidth_callback(NULL),
audio_messages(NULL),
bitrate_observer(NULL) {
remote_bitrate_estimator(NULL) {
}
/* id - Unique identifier of this RTP/RTCP module object
* audio - True for a audio version of the RTP/RTCP module
@ -54,8 +56,8 @@ class RtpRtcp : public Module {
* bandwidth_callback - Called when we receive a changed estimate from
* the receiver of out stream.
* audio_messages - Telehone events.
* bitrate_observer - Called when the estimate of the incoming RTP
* stream changes.
* remote_bitrate_estimator - Estimates the bandwidth available for a set of
* streams from the same client.
*/
int32_t id;
bool audio;
@ -68,7 +70,7 @@ class RtpRtcp : public Module {
RtcpIntraFrameObserver* intra_frame_callback;
RtcpBandwidthObserver* bandwidth_callback;
RtpAudioFeedback* audio_messages;
RtpRemoteBitrateObserver* bitrate_observer;
RemoteBitrateEstimator* remote_bitrate_estimator;
};
/*
* Create a RTP/RTCP module object using the system clock.

View File

@ -251,16 +251,5 @@ class RtpRtcpClock {
virtual void CurrentNTP(WebRtc_UWord32& secs, WebRtc_UWord32& frac) = 0;
};
// RtpReceiveBitrateUpdate is used to signal changes in bitrate estimates for
// the incoming stream.
class RtpRemoteBitrateObserver {
public:
// Called when a receive channel has a new bitrate estimate for the incoming
// stream.
virtual void OnReceiveBitrateChanged(uint32_t ssrc,
uint32_t bitrate) = 0;
virtual ~RtpRemoteBitrateObserver() {}
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_

View File

@ -8,7 +8,10 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "../testing/gmock/include/gmock/gmock.h"
#ifndef WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTP_RTCP_H_
#define WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTP_RTCP_H_
#include <gmock/gmock.h>
#include "modules/interface/module.h"
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
@ -211,7 +214,7 @@ class MockRtpRtcp : public RtpRtcp {
MOCK_METHOD3(SetREMBData,
WebRtc_Word32(const WebRtc_UWord32 bitrate, const WebRtc_UWord8 numberOfSSRC, const WebRtc_UWord32* SSRC));
MOCK_METHOD1(SetRemoteBitrateObserver,
bool(RtpRemoteBitrateObserver*));
bool(RemoteBitrateObserver*));
MOCK_CONST_METHOD0(IJ,
bool());
MOCK_METHOD1(SetIJStatus,
@ -285,3 +288,5 @@ class MockRtpRtcp : public RtpRtcp {
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTP_RTCP_H_

View File

@ -55,32 +55,6 @@ private:
WebRtc_UWord32 _packetCount;
};
struct DataTimeSizeTuple
{
DataTimeSizeTuple(WebRtc_UWord32 sizeBytes, WebRtc_Word64 timeCompleteMs) :
_sizeBytes(sizeBytes),
_timeCompleteMs(timeCompleteMs) {}
WebRtc_UWord32 _sizeBytes;
WebRtc_Word64 _timeCompleteMs;
};
class BitRateStats
{
public:
BitRateStats();
~BitRateStats();
void Init();
void Update(WebRtc_UWord32 packetSizeBytes, WebRtc_Word64 nowMs);
WebRtc_UWord32 BitRate(WebRtc_Word64 nowMs);
private:
void EraseOld(WebRtc_Word64 nowMs);
std::list<DataTimeSizeTuple*> _dataSamples;
WebRtc_UWord32 _accumulatedBytes;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_

View File

@ -11,8 +11,6 @@
#include "Bitrate.h"
#include "rtp_utility.h"
#define BITRATE_AVERAGE_WINDOW 2000
namespace webrtc {
Bitrate::Bitrate(RtpRtcpClock* clock) :
_clock(*clock),
@ -112,77 +110,4 @@ Bitrate::Process()
}
}
BitRateStats::BitRateStats()
:_dataSamples(), _accumulatedBytes(0)
{
}
BitRateStats::~BitRateStats()
{
while (_dataSamples.size() > 0)
{
delete _dataSamples.front();
_dataSamples.pop_front();
}
}
void BitRateStats::Init()
{
_accumulatedBytes = 0;
while (_dataSamples.size() > 0)
{
delete _dataSamples.front();
_dataSamples.pop_front();
}
}
void BitRateStats::Update(WebRtc_UWord32 packetSizeBytes, WebRtc_Word64 nowMs)
{
// Find an empty slot for storing the new sample and at the same time
// accumulate the history.
_dataSamples.push_back(new DataTimeSizeTuple(packetSizeBytes, nowMs));
_accumulatedBytes += packetSizeBytes;
EraseOld(nowMs);
}
void BitRateStats::EraseOld(WebRtc_Word64 nowMs)
{
while (_dataSamples.size() > 0)
{
if (nowMs - _dataSamples.front()->_timeCompleteMs >
BITRATE_AVERAGE_WINDOW)
{
// Delete old sample
_accumulatedBytes -= _dataSamples.front()->_sizeBytes;
delete _dataSamples.front();
_dataSamples.pop_front();
}
else
{
break;
}
}
}
WebRtc_UWord32 BitRateStats::BitRate(WebRtc_Word64 nowMs)
{
// Calculate the average bit rate the past BITRATE_AVERAGE_WINDOW ms.
// Removes any old samples from the list.
EraseOld(nowMs);
WebRtc_Word64 timeOldest = nowMs;
if (_dataSamples.size() > 0)
{
timeOldest = _dataSamples.front()->_timeCompleteMs;
}
// Update average bit rate
float denom = static_cast<float>(nowMs - timeOldest);
if (nowMs == timeOldest)
{
// Calculate with a one second window when we haven't
// received more than one packet.
denom = 1000.0;
}
return static_cast<WebRtc_UWord32>(_accumulatedBytes * 8.0f * 1000.0f /
denom + 0.5f);
}
} // namespace webrtc

View File

@ -8,12 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_RECEIVER_VIDEO_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_RECEIVER_VIDEO_H_
#include "modules/rtp_rtcp/source/rtp_receiver_video.h"
namespace webrtc {
class MockRTPReceiverVideo : public RTPReceiverVideo {
public:
MockRTPReceiverVideo() : RTPReceiverVideo(0, NULL, NULL) {}
MOCK_METHOD1(ChangeUniqueId,
void(const WebRtc_Word32 id));
MOCK_METHOD3(ReceiveRecoveredPacketCallback,
@ -39,3 +43,5 @@ class MockRTPReceiverVideo : public RTPReceiverVideo {
};
} // namespace webrtc
#endif //WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_RECEIVER_VIDEO_H_

View File

@ -16,7 +16,8 @@
#include "rtcp_sender.h"
#include "rtcp_receiver.h"
#include "rtp_rtcp_impl.h"
#include "bwe_defines.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h"
namespace {
@ -57,7 +58,9 @@ class TestTransport : public Transport {
class RtcpFormatRembTest : public ::testing::Test {
protected:
RtcpFormatRembTest() {};
RtcpFormatRembTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {}
virtual void SetUp();
virtual void TearDown();
@ -66,6 +69,8 @@ class RtcpFormatRembTest : public ::testing::Test {
RTCPSender* rtcp_sender_;
RTCPReceiver* rtcp_receiver_;
TestTransport* test_transport_;
MockRemoteBitrateObserver remote_bitrate_observer_;
RemoteBitrateEstimator remote_bitrate_estimator_;
};
void RtcpFormatRembTest::SetUp() {
@ -74,6 +79,7 @@ void RtcpFormatRembTest::SetUp() {
configuration.id = 0;
configuration.audio = false;
configuration.clock = system_clock_;
configuration.remote_bitrate_estimator = &remote_bitrate_estimator_;
dummy_rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
rtcp_sender_ = new RTCPSender(0, false, system_clock_, dummy_rtp_rtcp_impl_);
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, dummy_rtp_rtcp_impl_);

View File

@ -12,10 +12,13 @@
/*
* This file includes unit tests for the RTCPReceiver.
*/
#include <gmock/gmock.h>
#include <gtest/gtest.h>
// Note: This file has no directory. Lint warning must be ignored.
#include "common_types.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h"
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "modules/rtp_rtcp/source/rtcp_sender.h"
#include "modules/rtp_rtcp/source/rtcp_receiver.h"
@ -179,15 +182,19 @@ class TestTransport : public Transport,
class RtcpReceiverTest : public ::testing::Test {
protected:
RtcpReceiverTest() {
RtcpReceiverTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {
// system_clock_ = ModuleRTPUtility::GetSystemClock();
system_clock_ = new FakeSystemClock();
test_transport_ = new TestTransport();
RtpRtcp::Configuration configuration;
configuration.id = 0;
configuration.audio = false;
configuration.clock = system_clock_;
configuration.outgoing_transport = test_transport_;
configuration.remote_bitrate_estimator = &remote_bitrate_estimator_;
rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
rtcp_receiver_ = new RTCPReceiver(0, system_clock_, rtp_rtcp_impl_);
test_transport_->SetRTCPReceiver(rtcp_receiver_);
@ -219,6 +226,8 @@ class RtcpReceiverTest : public ::testing::Test {
RTCPReceiver* rtcp_receiver_;
TestTransport* test_transport_;
RTCPHelp::RTCPPacketInformation rtcp_packet_info_;
MockRemoteBitrateObserver remote_bitrate_observer_;
RemoteBitrateEstimator remote_bitrate_estimator_;
};

View File

@ -10,15 +10,15 @@
#include "rtcp_sender.h"
#include <string.h> // memcpy
#include <cassert> // assert
#include <cstdlib> // rand
#include <string.h> // memcpy
#include "trace.h"
#include "common_types.h"
#include "critical_section_wrapper.h"
#include "rtp_rtcp_impl.h"
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/trace.h"
namespace webrtc {
@ -66,12 +66,10 @@ RTCPSender::RTCPSender(const WebRtc_Word32 id,
_sizeRembSSRC(0),
_rembSSRC(NULL),
_rembBitrate(0),
_bitrate_observer(NULL),
_tmmbrHelp(),
_tmmbr_Send(0),
_packetOH_Send(0),
_remoteRateControl(),
_appSend(false),
_appSubType(0),
@ -130,7 +128,7 @@ RTCPSender::Init()
_sequenceNumberFIR = 0;
_tmmbr_Send = 0;
_packetOH_Send = 0;
_remoteRateControl.Reset();
//_remoteRateControl.Reset();
_nextTimeToSendRTCP = 0;
_CSRCs = 0;
_appSend = false;
@ -261,22 +259,6 @@ RTCPSender::SetREMBData(const WebRtc_UWord32 bitrate,
return 0;
}
bool RTCPSender::SetRemoteBitrateObserver(RtpRemoteBitrateObserver* observer) {
CriticalSectionScoped lock(_criticalSectionRTCPSender);
if (observer && _bitrate_observer) {
return false;
}
_bitrate_observer = observer;
return true;
}
void RTCPSender::UpdateRemoteBitrateEstimate(unsigned int target_bitrate) {
CriticalSectionScoped lock(_criticalSectionRTCPSender);
if (_bitrate_observer) {
_bitrate_observer->OnReceiveBitrateChanged(_remoteSSRC, target_bitrate);
}
}
bool
RTCPSender::TMMBR() const
{
@ -327,7 +309,7 @@ RTCPSender::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
_remoteSSRC = ssrc;
_remoteRateControl.Reset();
//_remoteRateControl.Reset();
return 0;
}
@ -1104,25 +1086,11 @@ RTCPSender::BuildREMB(WebRtc_UWord8* rtcpbuffer, WebRtc_UWord32& pos)
return 0;
}
WebRtc_UWord32
RTCPSender::CalculateNewTargetBitrate(WebRtc_UWord32 RTT)
void
RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
WebRtc_UWord32 target_bitrate =
_remoteRateControl.UpdateBandwidthEstimate(RTT, _clock.GetTimeInMS());
_tmmbr_Send = target_bitrate / 1000;
return target_bitrate;
}
WebRtc_UWord32 RTCPSender::LatestBandwidthEstimate() const {
CriticalSectionScoped lock(_criticalSectionRTCPSender);
return _remoteRateControl.LatestEstimate();
}
bool
RTCPSender::ValidBitrateEstimate() const {
CriticalSectionScoped lock(_criticalSectionRTCPSender);
return _remoteRateControl.ValidEstimate();
}
WebRtc_Word32
@ -2163,12 +2131,4 @@ RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
}
return -1;
}
RateControlRegion
RTCPSender::UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse)
{
CriticalSectionScoped lock(_criticalSectionRTCPSender);
return _remoteRateControl.Update(rateControlInput, firstOverUse,
_clock.GetTimeInMS());
}
} // namespace webrtc

View File

@ -17,8 +17,10 @@
#include "rtcp_utility.h"
#include "rtp_utility.h"
#include "rtp_rtcp_defines.h"
#include "remote_rate_control.h"
#include "scoped_ptr.h"
#include "tmmbr_help.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
namespace webrtc {
@ -87,10 +89,6 @@ public:
const WebRtc_UWord8 numberOfSSRC,
const WebRtc_UWord32* SSRC);
bool SetRemoteBitrateObserver(RtpRemoteBitrateObserver* observer);
void UpdateRemoteBitrateEstimate(unsigned int target_bitrate);
/*
* TMMBR
*/
@ -124,19 +122,7 @@ public:
WebRtc_Word32 SetCSRCStatus(const bool include);
/*
* New bandwidth estimation
*/
RateControlRegion UpdateOverUseState(const RateControlInput& rateControlInput, bool& firstOverUse);
WebRtc_UWord32 CalculateNewTargetBitrate(WebRtc_UWord32 RTT);
WebRtc_UWord32 LatestBandwidthEstimate() const;
// Returns true if there is a valid estimate of the incoming bitrate, false
// otherwise.
bool ValidBitrateEstimate() const;
void SetTargetBitrate(unsigned int target_bitrate);
private:
WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
@ -240,12 +226,10 @@ private:
WebRtc_UWord8 _sizeRembSSRC;
WebRtc_UWord32* _rembSSRC;
WebRtc_UWord32 _rembBitrate;
RtpRemoteBitrateObserver* _bitrate_observer;
TMMBRHelp _tmmbrHelp;
WebRtc_UWord32 _tmmbr_Send;
WebRtc_UWord32 _packetOH_Send;
RemoteRateControl _remoteRateControl;
// APP
bool _appSend;

View File

@ -13,13 +13,16 @@
* This file includes unit tests for the RTCPSender.
*/
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "common_types.h"
#include "rtp_utility.h"
#include "rtcp_sender.h"
#include "rtcp_receiver.h"
#include "rtp_rtcp_impl.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h"
#include "modules/rtp_rtcp/source/rtcp_receiver.h"
#include "modules/rtp_rtcp/source/rtcp_sender.h"
#include "modules/rtp_rtcp/source/rtp_utility.h"
#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
namespace webrtc {
@ -94,7 +97,9 @@ class TestTransport : public Transport,
class RtcpSenderTest : public ::testing::Test {
protected:
RtcpSenderTest() {
RtcpSenderTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {
system_clock_ = ModuleRTPUtility::GetSystemClock();
test_transport_ = new TestTransport();
@ -104,6 +109,7 @@ class RtcpSenderTest : public ::testing::Test {
configuration.clock = system_clock_;
configuration.incoming_data = test_transport_;
configuration.outgoing_transport = test_transport_;
configuration.remote_bitrate_estimator = &remote_bitrate_estimator_;
rtp_rtcp_impl_ = new ModuleRtpRtcpImpl(configuration);
rtcp_sender_ = new RTCPSender(0, false, system_clock_, rtp_rtcp_impl_);
@ -132,6 +138,8 @@ class RtcpSenderTest : public ::testing::Test {
RTCPSender* rtcp_sender_;
RTCPReceiver* rtcp_receiver_;
TestTransport* test_transport_;
MockRemoteBitrateObserver remote_bitrate_observer_;
RemoteBitrateEstimator remote_bitrate_estimator_;
enum {kMaxPacketLength = 1500};
uint8_t packet_[kMaxPacketLength];

View File

@ -32,9 +32,10 @@ using ModuleRTPUtility::VideoPayload;
RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
const bool audio,
RtpRtcpClock* clock,
RemoteBitrateEstimator* remote_bitrate,
ModuleRtpRtcpImpl* owner) :
RTPReceiverAudio(id),
RTPReceiverVideo(id, owner),
RTPReceiverVideo(id, remote_bitrate, owner),
Bitrate(clock),
_id(id),
_audio(audio),
@ -1083,7 +1084,6 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
// reset last report
ResetStatistics();
RTPReceiverVideo::ResetOverUseDetector();
_lastReceivedTimestamp = 0;
_lastReceivedSequenceNumber = 0;

View File

@ -35,6 +35,7 @@ public:
RTPReceiver(const WebRtc_Word32 id,
const bool audio,
RtpRtcpClock* clock,
RemoteBitrateEstimator* remote_bitrate,
ModuleRtpRtcpImpl* owner);
virtual ~RTPReceiver();

View File

@ -26,20 +26,8 @@ WebRtc_UWord32 BitRateBPS(WebRtc_UWord16 x )
return (x & 0x3fff) * WebRtc_UWord32(pow(10.0f,(2 + (x >> 14))));
}
RTPReceiverVideo::RTPReceiverVideo()
: _id(0),
_rtpRtcp(NULL),
_criticalSectionReceiverVideo(
CriticalSectionWrapper::CreateCriticalSection()),
_currentFecFrameDecoded(false),
_receiveFEC(NULL),
_overUseDetector(),
_videoBitRate(),
_lastBitRateChange(0),
_packetOverHead(28) {
}
RTPReceiverVideo::RTPReceiverVideo(const WebRtc_Word32 id,
RemoteBitrateEstimator* remote_bitrate,
ModuleRtpRtcpImpl* owner)
: _id(id),
_rtpRtcp(owner),
@ -47,9 +35,7 @@ RTPReceiverVideo::RTPReceiverVideo(const WebRtc_Word32 id,
CriticalSectionWrapper::CreateCriticalSection()),
_currentFecFrameDecoded(false),
_receiveFEC(NULL),
_overUseDetector(),
_videoBitRate(),
_lastBitRateChange(0),
remote_bitrate_(remote_bitrate),
_packetOverHead(28) {
}
@ -87,12 +73,6 @@ ModuleRTPUtility::Payload* RTPReceiverVideo::RegisterReceiveVideoPayload(
return payload;
}
void RTPReceiverVideo::ResetOverUseDetector() {
_overUseDetector.Reset();
_videoBitRate.Init();
_lastBitRateChange = 0;
}
// we have no critext when calling this
// we are not allowed to have any critsects when calling
// CallbackOfReceivedPayloadData
@ -109,14 +89,15 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecific(
_criticalSectionReceiverVideo->Enter();
_videoBitRate.Update(payloadDataLength + rtpHeader->header.paddingLength,
nowMS);
// Add headers, ideally we would like to include for instance
// Ethernet header here as well.
const WebRtc_UWord16 packetSize = payloadDataLength + _packetOverHead +
rtpHeader->header.headerLength + rtpHeader->header.paddingLength;
_overUseDetector.Update(*rtpHeader, packetSize, nowMS);
remote_bitrate_->IncomingPacket(rtpHeader->header.ssrc,
packetSize,
nowMS,
rtpHeader->header.timestamp,
-1);
if (isRED) {
if(_receiveFEC == NULL) {
@ -154,24 +135,6 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecific(
payloadDataLength,
videoType);
}
// Update the remote rate control object and update the overuse
// detector with the current rate control region.
_criticalSectionReceiverVideo->Enter();
const RateControlInput input(_overUseDetector.State(),
_videoBitRate.BitRate(nowMS),
_overUseDetector.NoiseVar());
_criticalSectionReceiverVideo->Leave();
// Call the callback outside critical section
if (_rtpRtcp) {
const RateControlRegion region = _rtpRtcp->OnOverUseStateUpdate(input);
_criticalSectionReceiverVideo->Enter();
_overUseDetector.SetRateControlRegion(region);
_criticalSectionReceiverVideo->Leave();
}
return retVal;
}

View File

@ -16,9 +16,11 @@
#include "typedefs.h"
#include "overuse_detector.h"
#include "remote_rate_control.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/remote_bitrate_estimator/overuse_detector.h"
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
#include "Bitrate.h"
#include "scoped_ptr.h"
namespace webrtc {
class ReceiverFEC;
@ -27,8 +29,9 @@ class CriticalSectionWrapper;
class RTPReceiverVideo {
public:
RTPReceiverVideo();
RTPReceiverVideo(const WebRtc_Word32 id, ModuleRtpRtcpImpl* owner);
RTPReceiverVideo(const WebRtc_Word32 id,
RemoteBitrateEstimator* remote_bitrate,
ModuleRtpRtcpImpl* owner);
virtual ~RTPReceiverVideo();
@ -55,8 +58,6 @@ class RTPReceiverVideo {
void SetPacketOverHead(WebRtc_UWord16 packetOverHead);
protected:
void ResetOverUseDetector();
virtual WebRtc_Word32 CallbackOfReceivedPayloadData(
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
@ -106,9 +107,7 @@ class RTPReceiverVideo {
ReceiverFEC* _receiveFEC;
// BWE
OverUseDetector _overUseDetector;
BitRateStats _videoBitRate;
WebRtc_Word64 _lastBitRateChange;
RemoteBitrateEstimator* remote_bitrate_;
WebRtc_UWord16 _packetOverHead;
};
} // namespace webrtc

View File

@ -13,6 +13,7 @@
'type': '<(library)',
'dependencies': [
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
'<(webrtc_root)/modules/modules.gyp:remote_bitrate_estimator',
],
'include_dirs': [
'../interface',
@ -67,12 +68,8 @@
'forward_error_correction.h',
'forward_error_correction_internal.cc',
'forward_error_correction_internal.h',
'overuse_detector.cc',
'overuse_detector.h',
'producer_fec.cc',
'producer_fec.h',
'remote_rate_control.cc',
'remote_rate_control.h',
'rtp_packet_history.cc',
'rtp_packet_history.h',
'rtp_receiver_video.cc',

View File

@ -54,7 +54,7 @@ RtpRtcp* RtpRtcp::CreateRtpRtcp(const RtpRtcp::Configuration& configuration) {
ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
: _rtpSender(configuration.id, configuration.audio, configuration.clock),
_rtpReceiver(configuration.id, configuration.audio, configuration.clock,
this),
configuration.remote_bitrate_estimator, this),
_rtcpSender(configuration.id, configuration.audio, configuration.clock,
this),
_rtcpReceiver(configuration.id, configuration.clock, this),
@ -80,7 +80,8 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
_nackLastTimeSent(0),
_nackLastSeqNumberSent(0),
_simulcast(false),
_keyFrameReqMethod(kKeyFrameReqFirRtp)
_keyFrameReqMethod(kKeyFrameReqFirRtp),
remote_bitrate_(configuration.remote_bitrate_estimator)
#ifdef MATLAB
, _plot1(NULL)
#endif
@ -102,8 +103,6 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
_rtpSender.RegisterSendTransport(configuration.outgoing_transport);
_rtcpSender.RegisterSendTransport(configuration.outgoing_transport);
_rtcpSender.SetRemoteBitrateObserver(configuration.bitrate_observer);
// make sure that RTCP objects are aware of our SSRC
WebRtc_UWord32 SSRC = _rtpSender.SSRC();
_rtcpSender.SetSSRC(SSRC);
@ -224,15 +223,16 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
// default module or no RTCP received yet.
max_rtt = kDefaultRtt;
}
if (_rtcpSender.ValidBitrateEstimate()) {
if (REMB()) {
uint32_t target_bitrate =
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
} else if (TMMBR()) {
_rtcpSender.CalculateNewTargetBitrate(max_rtt);
remote_bitrate_->SetRtt(max_rtt);
remote_bitrate_->UpdateEstimate(_rtpReceiver.SSRC(), now);
if (TMMBR()) {
unsigned int target_bitrate = 0;
if (remote_bitrate_->LatestEstimate(_rtpReceiver.SSRC(),
&target_bitrate)) {
_rtcpSender.SetTargetBitrate(target_bitrate);
}
}
_rtcpSender.SendRTCP(kRtcpReport);
}
@ -1882,35 +1882,12 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
int ModuleRtpRtcpImpl::EstimatedReceiveBandwidth(
WebRtc_UWord32* available_bandwidth) const {
if (!_rtcpSender.ValidBitrateEstimate())
if (!remote_bitrate_->LatestEstimate(_rtpReceiver.SSRC(),
available_bandwidth))
return -1;
*available_bandwidth = _rtcpSender.LatestBandwidthEstimate();
return 0;
}
RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate(
const RateControlInput& rateControlInput) {
bool firstOverUse = false;
RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput,
firstOverUse);
if (firstOverUse) {
// Send TMMBR or REMB immediately.
WebRtc_UWord16 RTT = 0;
_rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL);
// About to send TMMBR, first run remote rate control
// to get a target bit rate.
unsigned int target_bitrate =
_rtcpSender.CalculateNewTargetBitrate(RTT);
if (REMB()) {
_rtcpSender.UpdateRemoteBitrateEstimate(target_bitrate);
} else if (TMMBR()) {
_rtcpSender.SendRTCP(kRtcpTmmbr);
}
}
return region;
}
// bad state of RTP receiver request a keyframe
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
RequestKeyFrame();

View File

@ -428,8 +428,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 sendReport);
virtual RateControlRegion OnOverUseStateUpdate(const RateControlInput& rateControlInput);
// good state of RTP receiver inform sender
virtual WebRtc_Word32 SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID);
@ -506,6 +504,8 @@ private:
VideoCodec _sendVideoCodec;
KeyFrameRequestMethod _keyFrameReqMethod;
RemoteBitrateEstimator* remote_bitrate_;
#ifdef MATLAB
MatlabPlot* _plot1;
#endif

View File

@ -1,35 +0,0 @@
# Copyright (c) 2011 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.
{
'targets': [
{
'target_name': 'test_bwe',
'type': 'executable',
'dependencies': [
'rtp_rtcp',
'<(webrtc_root)/../test/test.gyp:test_support_main',
'<(webrtc_root)/../testing/gtest.gyp:gtest',
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'include_dirs': [
'../../source',
],
'sources': [
'unit_test.cc',
'../../source/bitrate.cc',
],
},
],
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:

View File

@ -38,7 +38,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
ProcessThread& module_process_thread,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RtpRemoteBitrateObserver* bitrate_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtpRtcp* default_rtp_rtcp)
: ViEFrameProviderBase(channel_id, engine_id),
channel_id_(channel_id),
@ -91,7 +91,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
configuration.rtcp_feedback = this;
configuration.intra_frame_callback = intra_frame_observer;
configuration.bandwidth_callback = bandwidth_observer;
configuration.bitrate_observer = bitrate_observer;
configuration.remote_bitrate_estimator = remote_bitrate_estimator;
rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
vie_receiver_.SetRtpRtcpModule(rtp_rtcp_.get());

View File

@ -15,6 +15,7 @@
#include <list>
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "modules/udp_transport/interface/udp_transport.h"
#include "modules/video_coding/main/interface/video_coding_defines.h"
@ -63,7 +64,7 @@ class ViEChannel
ProcessThread& module_process_thread,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RtpRemoteBitrateObserver* bitrate_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtpRtcp* default_rtp_rtcp);
~ViEChannel();

View File

@ -11,6 +11,7 @@
#include "video_engine/vie_channel_group.h"
#include "modules/bitrate_controller/include/bitrate_controller.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "video_engine/vie_channel.h"
#include "video_engine/vie_encoder.h"
@ -20,7 +21,8 @@ namespace webrtc {
ChannelGroup::ChannelGroup(ProcessThread* process_thread)
: remb_(new VieRemb(process_thread)),
bitrate_controller_(BitrateController::CreateBitrateController()) {
bitrate_controller_(BitrateController::CreateBitrateController()),
remote_bitrate_estimator_(new RemoteBitrateEstimator(remb_.get())) {
}
ChannelGroup::~ChannelGroup() {
@ -31,8 +33,9 @@ void ChannelGroup::AddChannel(int channel_id) {
channels_.insert(channel_id);
}
void ChannelGroup::RemoveChannel(int 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) {
@ -43,14 +46,14 @@ bool ChannelGroup::Empty() {
return channels_.empty();
}
RtpRemoteBitrateObserver* ChannelGroup::GetRtpRemoteBitrateObserver() {
return remb_.get();
}
BitrateController* ChannelGroup::GetBitrateController() {
return bitrate_controller_.get();
}
RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() {
return remote_bitrate_estimator_.get();
}
bool ChannelGroup::SetChannelRembStatus(int channel_id,
bool sender,
bool receiver,
@ -64,7 +67,7 @@ bool ChannelGroup::SetChannelRembStatus(int channel_id,
} else if (channel) {
channel->EnableRemb(false);
}
// Update the remb instance with necesary RTp modules.
// Update the REMB instance with necessary RTP modules.
RtpRtcp* rtp_module = channel->rtp_rtcp();
if (sender) {
remb_->AddRembSender(rtp_module);

View File

@ -19,7 +19,8 @@ namespace webrtc {
class BitrateController;
class ProcessThread;
class RtpRemoteBitrateObserver;
class RemoteBitrateEstimator;
class RemoteBitrateObserver;
class ViEChannel;
class ViEEncoder;
class VieRemb;
@ -32,7 +33,7 @@ class ChannelGroup {
~ChannelGroup();
void AddChannel(int channel_id);
void RemoveChannel(int channel_id);
void RemoveChannel(int channel_id, unsigned int ssrc);
bool HasChannel(int channel_id);
bool Empty();
@ -43,14 +44,14 @@ class ChannelGroup {
ViEEncoder* encoder);
BitrateController* GetBitrateController();
RtpRemoteBitrateObserver* GetRtpRemoteBitrateObserver();
RemoteBitrateEstimator* GetRemoteBitrateEstimator();
private:
typedef std::set<int> ChannelSet;
scoped_ptr<VieRemb> remb_;
scoped_ptr<BitrateController> bitrate_controller_;
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
ChannelSet channels_;
};

View File

@ -97,13 +97,12 @@ int ViEChannelManager::CreateChannel(int& channel_id) {
RtcpBandwidthObserver* bandwidth_observer =
bitrate_controller->CreateRtcpBandwidthObserver();
RtpRemoteBitrateObserver* bitrate_observer =
group->GetRtpRemoteBitrateObserver();
RemoteBitrateEstimator* remote_bitrate_estimator =
group->GetRemoteBitrateEstimator();
if (!(vie_encoder->Init() &&
CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
bitrate_observer))) {
remote_bitrate_estimator))) {
delete vie_encoder;
vie_encoder = NULL;
ReturnChannelId(new_channel_id);
@ -136,9 +135,8 @@ int ViEChannelManager::CreateChannel(int& channel_id,
RtcpBandwidthObserver* bandwidth_observer =
bitrate_controller->CreateRtcpBandwidthObserver();
RtpRemoteBitrateObserver* bitrate_observer =
channel_group->GetRtpRemoteBitrateObserver();
RemoteBitrateEstimator* remote_bitrate_estimator =
channel_group->GetRemoteBitrateEstimator();
ViEEncoder* vie_encoder = NULL;
if (sender) {
@ -148,7 +146,8 @@ int ViEChannelManager::CreateChannel(int& channel_id,
bitrate_controller);
if (!(vie_encoder->Init() &&
CreateChannelObject(new_channel_id, vie_encoder,
bandwidth_observer, bitrate_observer))) {
bandwidth_observer,
remote_bitrate_estimator))) {
delete vie_encoder;
vie_encoder = NULL;
}
@ -156,7 +155,7 @@ int ViEChannelManager::CreateChannel(int& channel_id,
vie_encoder = ViEEncoderPtr(original_channel);
assert(vie_encoder);
if (!CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
bitrate_observer)) {
remote_bitrate_estimator)) {
vie_encoder = NULL;
}
}
@ -202,7 +201,9 @@ int ViEChannelManager::DeleteChannel(int channel_id) {
group = FindGroup(channel_id);
group->SetChannelRembStatus(channel_id, false, false, vie_channel,
vie_encoder);
group->RemoveChannel(channel_id);
unsigned int ssrc = 0;
vie_channel->GetRemoteSSRC(ssrc);
group->RemoveChannel(channel_id, ssrc);
// Check if other channels are using the same encoder.
if (ChannelUsingViEEncoder(channel_id)) {
@ -326,7 +327,7 @@ bool ViEChannelManager::CreateChannelObject(
int channel_id,
ViEEncoder* vie_encoder,
RtcpBandwidthObserver* bandwidth_observer,
RtpRemoteBitrateObserver* bitrate_observer) {
RemoteBitrateEstimator* remote_bitrate_estimator) {
// Register the channel at the encoder.
RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule();
@ -335,7 +336,7 @@ bool ViEChannelManager::CreateChannelObject(
*module_process_thread_,
vie_encoder,
bandwidth_observer,
bitrate_observer,
remote_bitrate_estimator,
send_rtp_rtcp_module);
if (vie_channel->Init() != 0) {
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),

View File

@ -78,7 +78,7 @@ class ViEChannelManager: private ViEManagerBase {
// protected.
bool CreateChannelObject(int channel_id, ViEEncoder* vie_encoder,
RtcpBandwidthObserver* bandwidth_observer,
RtpRemoteBitrateObserver* bitrate_observer);
RemoteBitrateEstimator* remote_bitrate_estimator);
// Used by ViEChannelScoped, forcing a manager user to use scoped.
// Returns a pointer to the channel with id 'channelId'.

View File

@ -22,6 +22,7 @@
#include <map>
#include "modules/interface/module.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "system_wrappers/interface/scoped_ptr.h"
@ -31,7 +32,7 @@ class CriticalSectionWrapper;
class ProcessThread;
class RtpRtcp;
class VieRemb : public RtpRemoteBitrateObserver, public Module {
class VieRemb : public RemoteBitrateObserver, public Module {
public:
VieRemb(ProcessThread* process_thread);
~VieRemb();