Reland of BWE allocation strategy

TBR=stefan@webrtc.org,alexnarest@webrtc.org

Bug: webrtc:8243
Change-Id: Ie68e4f414b2ac32ba4e64877cb250fabcb089a07
Reviewed-on: https://webrtc-review.googlesource.com/13940
Commit-Queue: Alex Narest <alexnarest@webrtc.org>
Reviewed-by: Alex Narest <alexnarest@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20369}
This commit is contained in:
Alex Narest
2017-10-20 10:37:47 +02:00
committed by Commit Bot
parent b82de30080
commit 78609d5b6b
31 changed files with 543 additions and 24 deletions

View File

@ -786,6 +786,14 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// to the provided value. // to the provided value.
virtual RTCError SetBitrate(const BitrateParameters& bitrate) = 0; virtual RTCError SetBitrate(const BitrateParameters& bitrate) = 0;
// Sets current strategy. If not set default WebRTC allocator will be used.
// May be changed during an active session. The strategy
// ownership is passed with std::unique_ptr
// TODO(alexnarest): Make this pure virtual when tests will be updated
virtual void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) {}
// Returns the current SignalingState. // Returns the current SignalingState.
virtual SignalingState signaling_state() = 0; virtual SignalingState signaling_state() = 0;
virtual IceConnectionState ice_connection_state() = 0; virtual IceConnectionState ice_connection_state() = 0;

View File

@ -102,6 +102,9 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
const std::vector<cricket::Candidate>&); const std::vector<cricket::Candidate>&);
PROXY_METHOD1(void, RegisterUMAObserver, UMAObserver*) PROXY_METHOD1(void, RegisterUMAObserver, UMAObserver*)
PROXY_METHOD1(RTCError, SetBitrate, const BitrateParameters&); PROXY_METHOD1(RTCError, SetBitrate, const BitrateParameters&);
PROXY_METHOD1(void,
SetBitrateAllocationStrategy,
std::unique_ptr<rtc::BitrateAllocationStrategy>);
PROXY_METHOD0(SignalingState, signaling_state) PROXY_METHOD0(SignalingState, signaling_state)
PROXY_METHOD0(IceConnectionState, ice_connection_state) PROXY_METHOD0(IceConnectionState, ice_connection_state)
PROXY_METHOD0(IceGatheringState, ice_gathering_state) PROXY_METHOD0(IceGatheringState, ice_gathering_state)

View File

@ -236,6 +236,8 @@ void AudioSendStream::ConfigureStream(
void AudioSendStream::Start() { void AudioSendStream::Start() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1) { if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1) {
// Audio BWE is enabled.
transport_->packet_sender()->SetAccountForAudioPackets(true);
ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps); ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps);
} }

View File

@ -12,6 +12,7 @@
#include "call/bitrate_allocator.h" #include "call/bitrate_allocator.h"
#include <algorithm> #include <algorithm>
#include <memory>
#include <utility> #include <utility>
#include "modules/bitrate_controller/include/bitrate_controller.h" #include "modules/bitrate_controller/include/bitrate_controller.h"
@ -56,7 +57,8 @@ BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
clock_(Clock::GetRealTimeClock()), clock_(Clock::GetRealTimeClock()),
last_bwe_log_time_(0), last_bwe_log_time_(0),
total_requested_padding_bitrate_(0), total_requested_padding_bitrate_(0),
total_requested_min_bitrate_(0) { total_requested_min_bitrate_(0),
bitrate_allocation_strategy_(nullptr) {
sequenced_checker_.Detach(); sequenced_checker_.Detach();
} }
@ -199,6 +201,7 @@ void BitrateAllocator::UpdateAllocationLimits() {
void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) { void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
auto it = FindObserverConfig(observer); auto it = FindObserverConfig(observer);
if (it != bitrate_observer_configs_.end()) { if (it != bitrate_observer_configs_.end()) {
bitrate_observer_configs_.erase(it); bitrate_observer_configs_.erase(it);
@ -224,6 +227,13 @@ int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
} }
} }
void BitrateAllocator::SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
bitrate_allocation_strategy_ = std::move(bitrate_allocation_strategy);
}
BitrateAllocator::ObserverConfigs::iterator BitrateAllocator::ObserverConfigs::iterator
BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) { BitrateAllocator::FindObserverConfig(const BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
@ -241,6 +251,25 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
if (bitrate_observer_configs_.empty()) if (bitrate_observer_configs_.empty())
return ObserverAllocation(); return ObserverAllocation();
if (bitrate_allocation_strategy_ != nullptr) {
std::vector<const rtc::BitrateAllocationStrategy::TrackConfig*>
track_configs(bitrate_observer_configs_.size());
int i = 0;
for (const auto& c : bitrate_observer_configs_) {
track_configs[i++] = &c;
}
std::vector<uint32_t> track_allocations =
bitrate_allocation_strategy_->AllocateBitrates(bitrate, track_configs);
// The strategy should return allocation for all tracks.
RTC_CHECK(track_allocations.size() == bitrate_observer_configs_.size());
ObserverAllocation allocation;
auto track_allocations_it = track_allocations.begin();
for (const auto& observer_config : bitrate_observer_configs_) {
allocation[observer_config.observer] = *track_allocations_it++;
}
return allocation;
}
if (bitrate == 0) if (bitrate == 0)
return ZeroRateAllocation(); return ZeroRateAllocation();

View File

@ -14,10 +14,12 @@
#include <stdint.h> #include <stdint.h>
#include <map> #include <map>
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "rtc_base/bitrateallocationstrategy.h"
#include "rtc_base/sequenced_task_checker.h" #include "rtc_base/sequenced_task_checker.h"
namespace webrtc { namespace webrtc {
@ -94,32 +96,35 @@ class BitrateAllocator {
// the list of added observers, a best guess is returned. // the list of added observers, a best guess is returned.
int GetStartBitrate(BitrateAllocatorObserver* observer); int GetStartBitrate(BitrateAllocatorObserver* observer);
// Sets external allocation strategy. If strategy is not set default WebRTC
// allocation mechanism will be used. The strategy may be changed during call.
// Setting NULL value will restore default WEBRTC allocation strategy.
void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy);
private: private:
// Note: All bitrates for member variables and methods are in bps. // Note: All bitrates for member variables and methods are in bps.
struct ObserverConfig { struct ObserverConfig : rtc::BitrateAllocationStrategy::TrackConfig {
ObserverConfig(BitrateAllocatorObserver* observer, ObserverConfig(BitrateAllocatorObserver* observer,
uint32_t min_bitrate_bps, uint32_t min_bitrate_bps,
uint32_t max_bitrate_bps, uint32_t max_bitrate_bps,
uint32_t pad_up_bitrate_bps, uint32_t pad_up_bitrate_bps,
bool enforce_min_bitrate, bool enforce_min_bitrate,
std::string track_id) std::string track_id)
: observer(observer), : TrackConfig(min_bitrate_bps,
min_bitrate_bps(min_bitrate_bps), max_bitrate_bps,
max_bitrate_bps(max_bitrate_bps), enforce_min_bitrate,
track_id),
observer(observer),
pad_up_bitrate_bps(pad_up_bitrate_bps), pad_up_bitrate_bps(pad_up_bitrate_bps),
enforce_min_bitrate(enforce_min_bitrate),
allocated_bitrate_bps(-1), allocated_bitrate_bps(-1),
media_ratio(1.0), media_ratio(1.0) {}
track_id(track_id) {}
BitrateAllocatorObserver* observer; BitrateAllocatorObserver* observer;
uint32_t min_bitrate_bps;
uint32_t max_bitrate_bps;
uint32_t pad_up_bitrate_bps; uint32_t pad_up_bitrate_bps;
bool enforce_min_bitrate;
int64_t allocated_bitrate_bps; int64_t allocated_bitrate_bps;
double media_ratio; // Part of the total bitrate used for media [0.0, 1.0]. double media_ratio; // Part of the total bitrate used for media [0.0, 1.0].
std::string track_id;
}; };
// Calculates the minimum requested send bitrate and max padding bitrate and // Calculates the minimum requested send bitrate and max padding bitrate and
@ -172,6 +177,8 @@ class BitrateAllocator {
int64_t last_bwe_log_time_ RTC_GUARDED_BY(&sequenced_checker_); int64_t last_bwe_log_time_ RTC_GUARDED_BY(&sequenced_checker_);
uint32_t total_requested_padding_bitrate_ RTC_GUARDED_BY(&sequenced_checker_); uint32_t total_requested_padding_bitrate_ RTC_GUARDED_BY(&sequenced_checker_);
uint32_t total_requested_min_bitrate_ RTC_GUARDED_BY(&sequenced_checker_); uint32_t total_requested_min_bitrate_ RTC_GUARDED_BY(&sequenced_checker_);
std::unique_ptr<rtc::BitrateAllocationStrategy> bitrate_allocation_strategy_
RTC_GUARDED_BY(&sequenced_checker_);
}; };
} // namespace webrtc } // namespace webrtc
#endif // CALL_BITRATE_ALLOCATOR_H_ #endif // CALL_BITRATE_ALLOCATOR_H_

View File

@ -214,6 +214,10 @@ class Call : public webrtc::Call,
void SetBitrateConfigMask( void SetBitrateConfigMask(
const webrtc::Call::Config::BitrateConfigMask& bitrate_config) override; const webrtc::Call::Config::BitrateConfigMask& bitrate_config) override;
void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) override;
void SignalChannelNetworkState(MediaType media, NetworkState state) override; void SignalChannelNetworkState(MediaType media, NetworkState state) override;
void OnTransportOverheadChanged(MediaType media, void OnTransportOverheadChanged(MediaType media,
@ -1007,6 +1011,24 @@ void Call::UpdateCurrentBitrateConfig(const rtc::Optional<int>& new_start) {
config_.bitrate_config = updated; config_.bitrate_config = updated;
} }
void Call::SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) {
if (!worker_queue_.IsCurrent()) {
rtc::BitrateAllocationStrategy* strategy_raw =
bitrate_allocation_strategy.release();
auto functor = [this, strategy_raw]() {
SetBitrateAllocationStrategy(
rtc::WrapUnique<rtc::BitrateAllocationStrategy>(strategy_raw));
};
worker_queue_.PostTask([functor] { functor(); });
return;
}
RTC_DCHECK_RUN_ON(&worker_queue_);
bitrate_allocator_->SetBitrateAllocationStrategy(
std::move(bitrate_allocation_strategy));
}
void Call::SignalChannelNetworkState(MediaType media, NetworkState state) { void Call::SignalChannelNetworkState(MediaType media, NetworkState state) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_); RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_);
switch (media) { switch (media) {

View File

@ -24,6 +24,7 @@
#include "call/video_receive_stream.h" #include "call/video_receive_stream.h"
#include "call/video_send_stream.h" #include "call/video_send_stream.h"
#include "common_types.h" // NOLINT(build/include) #include "common_types.h" // NOLINT(build/include)
#include "rtc_base/bitrateallocationstrategy.h"
#include "rtc_base/networkroute.h" #include "rtc_base/networkroute.h"
#include "rtc_base/platform_file.h" #include "rtc_base/platform_file.h"
#include "rtc_base/socket.h" #include "rtc_base/socket.h"
@ -183,6 +184,10 @@ class Call {
virtual void SetBitrateConfigMask( virtual void SetBitrateConfigMask(
const Config::BitrateConfigMask& bitrate_mask) = 0; const Config::BitrateConfigMask& bitrate_mask) = 0;
virtual void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) = 0;
// TODO(skvlad): When the unbundled case with multiple streams for the same // TODO(skvlad): When the unbundled case with multiple streams for the same
// media type going over different networks is supported, track the state // media type going over different networks is supported, track the state
// for each stream separately. Right now it's global per media type. // for each stream separately. Right now it's global per media type.

View File

@ -418,19 +418,21 @@ RampUpDownUpTester::~RampUpDownUpTester() {}
void RampUpDownUpTester::PollStats() { void RampUpDownUpTester::PollStats() {
do { do {
if (send_stream_) { int transmit_bitrate_bps = 0;
bool suspended = false;
if (num_video_streams_ > 0) {
webrtc::VideoSendStream::Stats stats = send_stream_->GetStats(); webrtc::VideoSendStream::Stats stats = send_stream_->GetStats();
int transmit_bitrate_bps = 0;
for (auto it : stats.substreams) { for (auto it : stats.substreams) {
transmit_bitrate_bps += it.second.total_bitrate_bps; transmit_bitrate_bps += it.second.total_bitrate_bps;
} }
EvolveTestState(transmit_bitrate_bps, stats.suspended); suspended = stats.suspended;
} else if (num_audio_streams_ > 0 && sender_call_ != nullptr) { }
if (num_audio_streams_ > 0 && sender_call_ != nullptr) {
// An audio send stream doesn't have bitrate stats, so the call send BW is // An audio send stream doesn't have bitrate stats, so the call send BW is
// currently used instead. // currently used instead.
int transmit_bitrate_bps = sender_call_->GetStats().send_bandwidth_bps; transmit_bitrate_bps = sender_call_->GetStats().send_bandwidth_bps;
EvolveTestState(transmit_bitrate_bps, false);
} }
EvolveTestState(transmit_bitrate_bps, suspended);
} while (!stop_event_.Wait(kPollIntervalMs)); } while (!stop_event_.Wait(kPollIntervalMs));
} }

View File

@ -176,6 +176,7 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
if (is_ios) { if (is_ios) {
deps = [ deps = [
":AppRTCMobile_ios_frameworks", ":AppRTCMobile_ios_frameworks",
"../rtc_base:rtc_base",
] ]
} else { } else {
deps = [ deps = [
@ -206,6 +207,8 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
"objc/AppRTCMobile/ARDAppClient.m", "objc/AppRTCMobile/ARDAppClient.m",
"objc/AppRTCMobile/ARDAppEngineClient.h", "objc/AppRTCMobile/ARDAppEngineClient.h",
"objc/AppRTCMobile/ARDAppEngineClient.m", "objc/AppRTCMobile/ARDAppEngineClient.m",
"objc/AppRTCMobile/ARDBitrateAllocationStrategy.h",
"objc/AppRTCMobile/ARDBitrateAllocationStrategy.mm",
"objc/AppRTCMobile/ARDBitrateTracker.h", "objc/AppRTCMobile/ARDBitrateTracker.h",
"objc/AppRTCMobile/ARDBitrateTracker.m", "objc/AppRTCMobile/ARDBitrateTracker.m",
"objc/AppRTCMobile/ARDCaptureController.h", "objc/AppRTCMobile/ARDCaptureController.h",
@ -249,6 +252,7 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
deps = [ deps = [
":apprtc_common", ":apprtc_common",
":socketrocket", ":socketrocket",
"../rtc_base:rtc_base",
] ]
if (is_ios) { if (is_ios) {
deps += [ ":AppRTCMobile_ios_frameworks" ] deps += [ ":AppRTCMobile_ios_frameworks" ]

View File

@ -25,6 +25,7 @@
#import "WebRTC/RTCVideoTrack.h" #import "WebRTC/RTCVideoTrack.h"
#import "ARDAppEngineClient.h" #import "ARDAppEngineClient.h"
#import "ARDBitrateAllocationStrategy.h"
#import "ARDJoinResponse.h" #import "ARDJoinResponse.h"
#import "ARDMessageResponse.h" #import "ARDMessageResponse.h"
#import "ARDSettingsModel.h" #import "ARDSettingsModel.h"
@ -50,6 +51,7 @@ static NSString * const kARDMediaStreamId = @"ARDAMS";
static NSString * const kARDAudioTrackId = @"ARDAMSa0"; static NSString * const kARDAudioTrackId = @"ARDAMSa0";
static NSString * const kARDVideoTrackId = @"ARDAMSv0"; static NSString * const kARDVideoTrackId = @"ARDAMSv0";
static NSString * const kARDVideoTrackKind = @"video"; static NSString * const kARDVideoTrackKind = @"video";
static uint32_t const kSufficientAudioBitrate = 16000;
// TODO(tkchin): Add these as UI options. // TODO(tkchin): Add these as UI options.
static BOOL const kARDAppClientEnableTracing = NO; static BOOL const kARDAppClientEnableTracing = NO;
@ -104,6 +106,7 @@ static int const kKbpsMultiplier = 1000;
ARDTimerProxy *_statsTimer; ARDTimerProxy *_statsTimer;
ARDSettingsModel *_settings; ARDSettingsModel *_settings;
RTCVideoTrack *_localVideoTrack; RTCVideoTrack *_localVideoTrack;
ARDBitrateAllocationStrategy *_bitrateAllocationStrategy;
} }
@synthesize shouldGetStats = _shouldGetStats; @synthesize shouldGetStats = _shouldGetStats;
@ -306,12 +309,14 @@ static int const kKbpsMultiplier = 1000;
_hasReceivedSdp = NO; _hasReceivedSdp = NO;
_messageQueue = [NSMutableArray array]; _messageQueue = [NSMutableArray array];
_localVideoTrack = nil; _localVideoTrack = nil;
#if defined(WEBRTC_IOS) #if defined(WEBRTC_IOS)
[_factory stopAecDump]; [_factory stopAecDump];
[_peerConnection stopRtcEventLog]; [_peerConnection stopRtcEventLog];
#endif #endif
[_peerConnection close]; [_peerConnection close];
_peerConnection = nil; _peerConnection = nil;
_bitrateAllocationStrategy = nil;
self.state = kARDAppClientStateDisconnected; self.state = kARDAppClientStateDisconnected;
#if defined(WEBRTC_IOS) #if defined(WEBRTC_IOS)
if (kARDAppClientEnableTracing) { if (kARDAppClientEnableTracing) {
@ -533,8 +538,14 @@ static int const kKbpsMultiplier = 1000;
_peerConnection = [_factory peerConnectionWithConfiguration:config _peerConnection = [_factory peerConnectionWithConfiguration:config
constraints:constraints constraints:constraints
delegate:self]; delegate:self];
_bitrateAllocationStrategy = [ARDBitrateAllocationStrategy
createAudioPriorityBitrateAllocationStrategyForPeerConnection:_peerConnection
withAudioTrack:kARDAudioTrackId
sufficientAudioBitrate:kSufficientAudioBitrate];
// Create AV senders. // Create AV senders.
[self createMediaSenders]; [self createMediaSenders];
if (_isInitiator) { if (_isInitiator) {
// Send offer. // Send offer.
__weak ARDAppClient *weakSelf = self; __weak ARDAppClient *weakSelf = self;

View File

@ -0,0 +1,23 @@
/*
* Copyright 2017 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.
*/
#import <Foundation/Foundation.h>
#import "WebRTC/RTCPeerConnection.h"
@interface ARDBitrateAllocationStrategy : NSObject
+ (ARDBitrateAllocationStrategy*)
createAudioPriorityBitrateAllocationStrategyForPeerConnection:(RTCPeerConnection*)peerConnection
withAudioTrack:(NSString*)audioTrackID
sufficientAudioBitrate:(uint32_t)sufficientAudioBitrate;
- (instancetype)init NS_UNAVAILABLE;
@end

View File

@ -0,0 +1,40 @@
/*
* Copyright 2017 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.
*/
#import "ARDBitrateAllocationStrategy.h"
#import "WebRTC/RTCBitrateAllocationStrategy.h"
#include "rtc_base/bitrateallocationstrategy.h"
@implementation ARDBitrateAllocationStrategy
+ (ARDBitrateAllocationStrategy*)
createAudioPriorityBitrateAllocationStrategyForPeerConnection:(RTCPeerConnection*)peerConnection
withAudioTrack:(NSString*)audioTrackID
sufficientAudioBitrate:(uint32_t)sufficientAudioBitrate {
return [[ARDBitrateAllocationStrategy alloc] initWithPeerCoonnection:peerConnection
withAudioTrack:audioTrackID
sufficientAudioBitrate:sufficientAudioBitrate];
}
- (instancetype)initWithPeerCoonnection:(RTCPeerConnection*)peerConnection
withAudioTrack:(NSString*)audioTrackID
sufficientAudioBitrate:(uint32_t)sufficientAudioBitrate {
if (self = [super init]) {
[peerConnection
setBitrateAllocationStrategy:[[RTCBitrateAllocationStrategy alloc]
initWith:new rtc::AudioPriorityBitrateAllocationStrategy(
std::string(audioTrackID.UTF8String),
sufficientAudioBitrate)]];
}
return self;
}
@end

View File

@ -26,7 +26,8 @@
- (BOOL)application:(UIApplication *)application - (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *fieldTrials = @{ NSDictionary *fieldTrials = @{
kRTCFieldTrialH264HighProfileKey: kRTCFieldTrialEnabledValue, kRTCFieldTrialH264HighProfileKey : kRTCFieldTrialEnabledValue,
kRTCFieldTrialAudioSendSideBweKey : kRTCFieldTrialEnabledValue
}; };
RTCInitFieldTrialDictionary(fieldTrials); RTCInitFieldTrialDictionary(fieldTrials);
RTCInitializeSSL(); RTCInitializeSSL();

View File

@ -595,6 +595,12 @@ void FakeCall::SetBitrateConfigMask(
// TODO(zstein): not implemented // TODO(zstein): not implemented
} }
void FakeCall::SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy){
// TODO(alexnarest): not implemented
};
void FakeCall::SignalChannelNetworkState(webrtc::MediaType media, void FakeCall::SignalChannelNetworkState(webrtc::MediaType media,
webrtc::NetworkState state) { webrtc::NetworkState state) {
switch (media) { switch (media) {

View File

@ -296,6 +296,9 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
const webrtc::Call::Config::BitrateConfig& bitrate_config) override; const webrtc::Call::Config::BitrateConfig& bitrate_config) override;
void SetBitrateConfigMask( void SetBitrateConfigMask(
const webrtc::Call::Config::BitrateConfigMask& mask) override; const webrtc::Call::Config::BitrateConfigMask& mask) override;
void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) override;
void OnNetworkRouteChanged(const std::string& transport_name, void OnNetworkRouteChanged(const std::string& transport_name,
const rtc::NetworkRoute& network_route) override {} const rtc::NetworkRoute& network_route) override {}
void SignalChannelNetworkState(webrtc::MediaType media, void SignalChannelNetworkState(webrtc::MediaType media,

View File

@ -63,7 +63,8 @@ PacedSender::PacedSender(const Clock* clock,
packets_(rtc::MakeUnique<PacketQueue>(clock)), packets_(rtc::MakeUnique<PacketQueue>(clock)),
packet_counter_(0), packet_counter_(0),
pacing_factor_(kDefaultPaceMultiplier), pacing_factor_(kDefaultPaceMultiplier),
queue_time_limit(kMaxQueueLengthMs) { queue_time_limit(kMaxQueueLengthMs),
account_for_audio_(false) {
UpdateBudgetWithElapsedTime(kMinPacketLimitMs); UpdateBudgetWithElapsedTime(kMinPacketLimitMs);
} }
@ -154,6 +155,11 @@ void PacedSender::InsertPacket(RtpPacketSender::Priority priority,
retransmission, packet_counter_++)); retransmission, packet_counter_++));
} }
void PacedSender::SetAccountForAudioPackets(bool account_for_audio) {
rtc::CritScope cs(&critsect_);
account_for_audio_ = account_for_audio;
}
int64_t PacedSender::ExpectedQueueTimeMs() const { int64_t PacedSender::ExpectedQueueTimeMs() const {
rtc::CritScope cs(&critsect_); rtc::CritScope cs(&critsect_);
RTC_DCHECK_GT(pacing_bitrate_kbps_, 0); RTC_DCHECK_GT(pacing_bitrate_kbps_, 0);
@ -318,9 +324,7 @@ bool PacedSender::SendPacket(const PacketQueue::Packet& packet,
critsect_.Enter(); critsect_.Enter();
if (success) { if (success) {
// TODO(holmer): High priority packets should only be accounted for if we if (packet.priority != kHighPriority || account_for_audio_) {
// are allocating bandwidth for audio.
if (packet.priority != kHighPriority) {
// Update media bytes sent. // Update media bytes sent.
// TODO(eladalon): TimeToSendPacket() can also return |true| in some // TODO(eladalon): TimeToSendPacket() can also return |true| in some
// situations where nothing actually ended up being sent to the network, // situations where nothing actually ended up being sent to the network,

View File

@ -107,6 +107,12 @@ class PacedSender : public Pacer {
size_t bytes, size_t bytes,
bool retransmission) override; bool retransmission) override;
// Currently audio traffic is not accounted by pacer and passed through.
// With the introduction of audio BWE audio traffic will be accounted for
// the pacer budget calculation. The audio traffic still will be injected
// at high priority.
void SetAccountForAudioPackets(bool account_for_audio) override;
// Returns the time since the oldest queued packet was enqueued. // Returns the time since the oldest queued packet was enqueued.
virtual int64_t QueueInMs() const; virtual int64_t QueueInMs() const;
@ -192,6 +198,7 @@ class PacedSender : public Pacer {
float pacing_factor_ RTC_GUARDED_BY(critsect_); float pacing_factor_ RTC_GUARDED_BY(critsect_);
int64_t queue_time_limit RTC_GUARDED_BY(critsect_); int64_t queue_time_limit RTC_GUARDED_BY(critsect_);
bool account_for_audio_ RTC_GUARDED_BY(critsect_);
}; };
} // namespace webrtc } // namespace webrtc
#endif // MODULES_PACING_PACED_SENDER_H_ #endif // MODULES_PACING_PACED_SENDER_H_

View File

@ -68,6 +68,7 @@ class BbrPacedSender : public Pacer {
int64_t capture_time_ms, int64_t capture_time_ms,
size_t bytes, size_t bytes,
bool retransmission) override; bool retransmission) override;
void SetAccountForAudioPackets(bool account_for_audio) override {}
int64_t TimeUntilNextProcess() override; int64_t TimeUntilNextProcess() override;
void OnBytesAcked(size_t bytes) override; void OnBytesAcked(size_t bytes) override;
void Process() override; void Process() override;

View File

@ -498,6 +498,14 @@ class RtpPacketSender {
int64_t capture_time_ms, int64_t capture_time_ms,
size_t bytes, size_t bytes,
bool retransmission) = 0; bool retransmission) = 0;
// Currently audio traffic is not accounted by pacer and passed through.
// With the introduction of audio BWE audio traffic will be accounted for
// the pacer budget calculation. The audio traffic still will be injected
// at high priority.
// TODO(alexnarest): Make it pure virtual after rtp_sender_unittest will be
// updated to support it
virtual void SetAccountForAudioPackets(bool account_for_audio) {}
}; };
class TransportSequenceNumberAllocator { class TransportSequenceNumberAllocator {

View File

@ -1331,6 +1331,24 @@ RTCError PeerConnection::SetBitrate(const BitrateParameters& bitrate) {
return RTCError::OK(); return RTCError::OK();
} }
void PeerConnection::SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) {
rtc::Thread* worker_thread = factory_->worker_thread();
if (!worker_thread->IsCurrent()) {
rtc::BitrateAllocationStrategy* strategy_raw =
bitrate_allocation_strategy.release();
auto functor = [this, strategy_raw]() {
call_->SetBitrateAllocationStrategy(
rtc::WrapUnique<rtc::BitrateAllocationStrategy>(strategy_raw));
};
worker_thread->Invoke<void>(RTC_FROM_HERE, functor);
return;
}
RTC_DCHECK(call_.get());
call_->SetBitrateAllocationStrategy(std::move(bitrate_allocation_strategy));
}
std::unique_ptr<rtc::SSLCertificate> std::unique_ptr<rtc::SSLCertificate>
PeerConnection::GetRemoteAudioSSLCertificate() { PeerConnection::GetRemoteAudioSSLCertificate() {
if (!session_) { if (!session_) {

View File

@ -145,6 +145,10 @@ class PeerConnection : public PeerConnectionInterface,
RTCError SetBitrate(const BitrateParameters& bitrate) override; RTCError SetBitrate(const BitrateParameters& bitrate) override;
void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) override;
RTC_DEPRECATED bool StartRtcEventLog(rtc::PlatformFile file, RTC_DEPRECATED bool StartRtcEventLog(rtc::PlatformFile file,
int64_t max_size_bytes) override; int64_t max_size_bytes) override;
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) override; bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) override;

View File

@ -113,6 +113,8 @@ rtc_source_set("rtc_base_approved_generic") {
"bind.h", "bind.h",
"bitbuffer.cc", "bitbuffer.cc",
"bitbuffer.h", "bitbuffer.h",
"bitrateallocationstrategy.cc",
"bitrateallocationstrategy.h",
"buffer.h", "buffer.h",
"bufferqueue.cc", "bufferqueue.cc",
"bufferqueue.h", "bufferqueue.h",

View File

@ -0,0 +1,125 @@
/*
* Copyright 2017 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 "rtc_base/bitrateallocationstrategy.h"
#include <algorithm>
#include <utility>
namespace rtc {
std::vector<uint32_t> BitrateAllocationStrategy::SetAllBitratesToMinimum(
const ArrayView<const TrackConfig*> track_configs) {
std::vector<uint32_t> track_allocations;
for (const auto* track_config : track_configs) {
track_allocations.push_back(track_config->min_bitrate_bps);
}
return track_allocations;
}
std::vector<uint32_t> BitrateAllocationStrategy::DistributeBitratesEvenly(
const ArrayView<const TrackConfig*> track_configs,
uint32_t available_bitrate) {
std::vector<uint32_t> track_allocations =
SetAllBitratesToMinimum(track_configs);
uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0;
for (const auto* track_config : track_configs) {
sum_min_bitrates += track_config->min_bitrate_bps;
sum_max_bitrates += track_config->max_bitrate_bps;
}
if (sum_min_bitrates >= available_bitrate) {
return track_allocations;
} else if (available_bitrate >= sum_max_bitrates) {
auto track_allocations_it = track_allocations.begin();
for (const auto* track_config : track_configs) {
*track_allocations_it++ = track_config->max_bitrate_bps;
}
return track_allocations;
} else {
// If sum_min_bitrates < available_bitrate < sum_max_bitrates allocate
// bitrates evenly up to max_bitrate_bps starting from the track with the
// lowest max_bitrate_bps. Remainder of available bitrate split evenly among
// remaining tracks.
std::multimap<uint32_t, size_t> max_bitrate_sorted_configs;
for (const TrackConfig** track_configs_it = track_configs.begin();
track_configs_it != track_configs.end(); ++track_configs_it) {
max_bitrate_sorted_configs.insert(
std::make_pair((*track_configs_it)->max_bitrate_bps,
track_configs_it - track_configs.begin()));
}
uint32_t total_available_increase = available_bitrate - sum_min_bitrates;
int processed_configs = 0;
for (const auto& track_config_pair : max_bitrate_sorted_configs) {
uint32_t available_increase =
total_available_increase /
(static_cast<uint32_t>(track_configs.size() - processed_configs));
uint32_t consumed_increase =
std::min(track_configs[track_config_pair.second]->max_bitrate_bps -
track_configs[track_config_pair.second]->min_bitrate_bps,
available_increase);
track_allocations[track_config_pair.second] += consumed_increase;
total_available_increase -= consumed_increase;
++processed_configs;
}
return track_allocations;
}
}
AudioPriorityBitrateAllocationStrategy::AudioPriorityBitrateAllocationStrategy(
std::string audio_track_id,
uint32_t sufficient_audio_bitrate)
: audio_track_id_(audio_track_id),
sufficient_audio_bitrate_(sufficient_audio_bitrate) {}
std::vector<uint32_t> AudioPriorityBitrateAllocationStrategy::AllocateBitrates(
uint32_t available_bitrate,
const ArrayView<const TrackConfig*> track_configs) {
const TrackConfig* audio_track_config = NULL;
size_t audio_config_index = 0;
uint32_t sum_min_bitrates = 0;
for (const auto*& track_config : track_configs) {
sum_min_bitrates += track_config->min_bitrate_bps;
if (track_config->track_id == audio_track_id_) {
audio_track_config = track_config;
audio_config_index = &track_config - &track_configs[0];
}
}
if (audio_track_config == nullptr) {
return DistributeBitratesEvenly(track_configs, available_bitrate);
}
auto safe_sufficient_audio_bitrate = std::min(
std::max(audio_track_config->min_bitrate_bps, sufficient_audio_bitrate_),
audio_track_config->max_bitrate_bps);
if (available_bitrate <= sum_min_bitrates) {
return SetAllBitratesToMinimum(track_configs);
} else {
if (available_bitrate <= sum_min_bitrates + safe_sufficient_audio_bitrate -
audio_track_config->min_bitrate_bps) {
std::vector<uint32_t> track_allocations =
SetAllBitratesToMinimum(track_configs);
track_allocations[audio_config_index] +=
available_bitrate - sum_min_bitrates;
return track_allocations;
} else {
// Setting audio track minimum to safe_sufficient_audio_bitrate will
// allow using DistributeBitratesEvenly to allocate at least sufficient
// bitrate for audio and the rest evenly.
TrackConfig sufficient_track_config(*track_configs[audio_config_index]);
sufficient_track_config.min_bitrate_bps = safe_sufficient_audio_bitrate;
track_configs[audio_config_index] = &sufficient_track_config;
std::vector<uint32_t> track_allocations =
DistributeBitratesEvenly(track_configs, available_bitrate);
return track_allocations;
}
}
}
} // namespace rtc

View File

@ -0,0 +1,101 @@
/*
* Copyright 2017 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 RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_
#define RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "api/array_view.h"
#include "rtc_base/checks.h"
namespace rtc {
// Pluggable strategy allows configuration of bitrate allocation per media
// track.
//
// The strategy should provide allocation for every track passed with
// track_configs in AllocateBitrates. The allocations are constrained by
// max_bitrate_bps, min_bitrate_bps defining the track supported range and
// enforce_min_bitrate indicating if the track my be paused by allocating 0
// bitrate.
class BitrateAllocationStrategy {
public:
struct TrackConfig {
TrackConfig(uint32_t min_bitrate_bps,
uint32_t max_bitrate_bps,
bool enforce_min_bitrate,
std::string track_id)
: min_bitrate_bps(min_bitrate_bps),
max_bitrate_bps(max_bitrate_bps),
enforce_min_bitrate(enforce_min_bitrate),
track_id(track_id) {}
TrackConfig(const TrackConfig& track_config) = default;
virtual ~TrackConfig() = default;
TrackConfig() {}
// Minimum bitrate supported by track.
uint32_t min_bitrate_bps;
// Maximum bitrate supported by track.
uint32_t max_bitrate_bps;
// True means track may not be paused by allocating 0 bitrate.
bool enforce_min_bitrate;
// MediaStreamTrack ID as defined by application. May be empty.
std::string track_id;
};
static std::vector<uint32_t> SetAllBitratesToMinimum(
const ArrayView<const TrackConfig*> track_configs);
static std::vector<uint32_t> DistributeBitratesEvenly(
const ArrayView<const TrackConfig*> track_configs,
uint32_t available_bitrate);
// Strategy is expected to allocate all available_bitrate up to the sum of
// max_bitrate_bps of all tracks. If available_bitrate is less than the sum of
// min_bitrate_bps of all tracks, tracks having enforce_min_bitrate set to
// false may get 0 allocation and are suppoused to pause, tracks with
// enforce_min_bitrate set to true are expecting to get min_bitrate_bps.
//
// If the strategy will allocate more than available_bitrate it may cause
// overuse of the currently available network capacity and may cause increase
// in RTT and packet loss. Allocating less than available bitrate may cause
// available_bitrate decrease.
virtual std::vector<uint32_t> AllocateBitrates(
uint32_t available_bitrate,
const ArrayView<const TrackConfig*> track_configs) = 0;
virtual ~BitrateAllocationStrategy() = default;
};
// Simple allocation strategy giving priority to audio until
// sufficient_audio_bitrate is reached. Bitrate is distributed evenly between
// the tracks after sufficient_audio_bitrate is reached. This implementation
// does not pause tracks even if enforce_min_bitrate is false.
class AudioPriorityBitrateAllocationStrategy
: public BitrateAllocationStrategy {
public:
AudioPriorityBitrateAllocationStrategy(std::string audio_track_id,
uint32_t sufficient_audio_bitrate);
std::vector<uint32_t> AllocateBitrates(
uint32_t available_bitrate,
const ArrayView<const TrackConfig*> track_configs) override;
private:
std::string audio_track_id_;
uint32_t sufficient_audio_bitrate_;
};
} // namespace rtc
#endif // RTC_BASE_BITRATEALLOCATIONSTRATEGY_H_

View File

@ -386,6 +386,7 @@ if (is_ios || is_mac) {
"objc/Framework/Classes/PeerConnection/RTCAudioSource.mm", "objc/Framework/Classes/PeerConnection/RTCAudioSource.mm",
"objc/Framework/Classes/PeerConnection/RTCAudioTrack+Private.h", "objc/Framework/Classes/PeerConnection/RTCAudioTrack+Private.h",
"objc/Framework/Classes/PeerConnection/RTCAudioTrack.mm", "objc/Framework/Classes/PeerConnection/RTCAudioTrack.mm",
"objc/Framework/Classes/PeerConnection/RTCBitrateAllocationStrategy.mm",
"objc/Framework/Classes/PeerConnection/RTCConfiguration+Private.h", "objc/Framework/Classes/PeerConnection/RTCConfiguration+Private.h",
"objc/Framework/Classes/PeerConnection/RTCConfiguration.mm", "objc/Framework/Classes/PeerConnection/RTCConfiguration.mm",
"objc/Framework/Classes/PeerConnection/RTCDataChannel+Private.h", "objc/Framework/Classes/PeerConnection/RTCDataChannel+Private.h",
@ -453,6 +454,7 @@ if (is_ios || is_mac) {
"objc/Framework/Headers/WebRTC/RTCAVFoundationVideoSource.h", "objc/Framework/Headers/WebRTC/RTCAVFoundationVideoSource.h",
"objc/Framework/Headers/WebRTC/RTCAudioSource.h", "objc/Framework/Headers/WebRTC/RTCAudioSource.h",
"objc/Framework/Headers/WebRTC/RTCAudioTrack.h", "objc/Framework/Headers/WebRTC/RTCAudioTrack.h",
"objc/Framework/Headers/WebRTC/RTCBitrateAllocationStrategy.h",
"objc/Framework/Headers/WebRTC/RTCConfiguration.h", "objc/Framework/Headers/WebRTC/RTCConfiguration.h",
"objc/Framework/Headers/WebRTC/RTCDataChannel.h", "objc/Framework/Headers/WebRTC/RTCDataChannel.h",
"objc/Framework/Headers/WebRTC/RTCDataChannelConfiguration.h", "objc/Framework/Headers/WebRTC/RTCDataChannelConfiguration.h",

View File

@ -0,0 +1,28 @@
/*
* Copyright 2017 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.
*/
#import "WebRTC/RTCBitrateAllocationStrategy.h"
#include "rtc_base/bitrateallocationstrategy.h"
#include "rtc_base/checks.h"
@implementation RTCBitrateAllocationStrategy
@synthesize strategy = _strategy;
- (instancetype)initWith:(rtc::BitrateAllocationStrategy*)strategy {
RTC_DCHECK(strategy);
if (self = [super init]) {
_strategy = strategy;
}
return self;
}
@end

View File

@ -178,7 +178,6 @@
nativeConfig->ice_regather_interval_range = nativeConfig->ice_regather_interval_range =
rtc::Optional<rtc::IntervalRange>(*nativeIntervalRange); rtc::Optional<rtc::IntervalRange>(*nativeIntervalRange);
} }
return nativeConfig.release(); return nativeConfig.release();
} }

View File

@ -21,6 +21,7 @@
#import "RTCRtpReceiver+Private.h" #import "RTCRtpReceiver+Private.h"
#import "RTCRtpSender+Private.h" #import "RTCRtpSender+Private.h"
#import "RTCSessionDescription+Private.h" #import "RTCSessionDescription+Private.h"
#import "WebRTC/RTCBitrateAllocationStrategy.h"
#import "WebRTC/RTCLogging.h" #import "WebRTC/RTCLogging.h"
#include <memory> #include <memory>
@ -385,6 +386,15 @@ void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
return _peerConnection->SetBitrate(params).ok(); return _peerConnection->SetBitrate(params).ok();
} }
- (void)setBitrateAllocationStrategy:
(RTCBitrateAllocationStrategy *_Nullable)bitrateAllocationStrategy {
if (bitrateAllocationStrategy)
_peerConnection->SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>(bitrateAllocationStrategy.strategy));
else
_peerConnection->SetBitrateAllocationStrategy(nullptr);
}
- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath - (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
maxSizeInBytes:(int64_t)maxSizeInBytes { maxSizeInBytes:(int64_t)maxSizeInBytes {
RTC_DCHECK(filePath.length); RTC_DCHECK(filePath.length);

View File

@ -0,0 +1,32 @@
/*
* Copyright 2017 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.
*/
#import <WebRTC/RTCMacros.h>
#import <WebRTC/RTCMediaStreamTrack.h>
NS_ASSUME_NONNULL_BEGIN
namespace rtc {
class BitrateAllocationStrategy;
}
RTC_EXPORT
@interface RTCBitrateAllocationStrategy : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWith:(rtc::BitrateAllocationStrategy*)strategy;
/** Native bitrate allocation strategy. */
@property(nonatomic, readonly) rtc::BitrateAllocationStrategy* strategy;
@end
NS_ASSUME_NONNULL_END

View File

@ -24,6 +24,7 @@
@class RTCRtpSender; @class RTCRtpSender;
@class RTCSessionDescription; @class RTCSessionDescription;
@class RTCLegacyStatsReport; @class RTCLegacyStatsReport;
@class RTCBitrateAllocationStrategy;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -193,6 +194,13 @@ RTC_EXPORT
currentBitrateBps:(nullable NSNumber *)currentBitrateBps currentBitrateBps:(nullable NSNumber *)currentBitrateBps
maxBitrateBps:(nullable NSNumber *)maxBitrateBps; maxBitrateBps:(nullable NSNumber *)maxBitrateBps;
/** Sets current strategy. If not set default WebRTC allocator will be used.
* May be changed during an active session. The strategy
* ownership is passed with std::unique_ptr
*/
- (void)setBitrateAllocationStrategy:
(RTCBitrateAllocationStrategy *_Nullable)bitrateAllocationStrategy;
/** Start or stop recording an Rtc EventLog. */ /** Start or stop recording an Rtc EventLog. */
- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath - (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
maxSizeInBytes:(int64_t)maxSizeInBytes; maxSizeInBytes:(int64_t)maxSizeInBytes;

View File

@ -215,6 +215,10 @@ class RtpPacketSenderProxy : public RtpPacketSender {
} }
} }
void SetAccountForAudioPackets(bool account_for_audio) override {
RTC_NOTREACHED();
}
private: private:
rtc::ThreadChecker thread_checker_; rtc::ThreadChecker thread_checker_;
rtc::CriticalSection crit_; rtc::CriticalSection crit_;