BWE allocation strategy allows controlling of bitrate allocation with WEBRTC external logic.

This CL implements the main logic and IOS appRTC integration.

Unit tests and Android appRTC will be in separate CL.

Bug: webrtc:8243
Change-Id: If8e5195294046a47316e9fade1b0dfec211155e1
Reviewed-on: https://webrtc-review.googlesource.com/4860
Commit-Queue: Alex Narest <alexnarest@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20329}
This commit is contained in:
Alex Narest
2017-10-17 19:49:15 +02:00
committed by Commit Bot
parent 1b0eae3c81
commit 54d1da13a5
30 changed files with 534 additions and 18 deletions

View File

@ -786,6 +786,13 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
// to the provided value.
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
virtual void SetBitrateAllocationStrategy(
std::unique_ptr<rtc::BitrateAllocationStrategy>
bitrate_allocation_strategy) = 0;
// Returns the current SignalingState.
virtual SignalingState signaling_state() = 0;
virtual IceConnectionState ice_connection_state() = 0;

View File

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

View File

@ -236,6 +236,8 @@ void AudioSendStream::ConfigureStream(
void AudioSendStream::Start() {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
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);
}

View File

@ -12,6 +12,7 @@
#include "call/bitrate_allocator.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "modules/bitrate_controller/include/bitrate_controller.h"
@ -56,7 +57,8 @@ BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
clock_(Clock::GetRealTimeClock()),
last_bwe_log_time_(0),
total_requested_padding_bitrate_(0),
total_requested_min_bitrate_(0) {
total_requested_min_bitrate_(0),
bitrate_allocation_strategy_(nullptr) {
sequenced_checker_.Detach();
}
@ -199,6 +201,7 @@ void BitrateAllocator::UpdateAllocationLimits() {
void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
auto it = FindObserverConfig(observer);
if (it != bitrate_observer_configs_.end()) {
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::FindObserverConfig(const BitrateAllocatorObserver* observer) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
@ -241,6 +251,25 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::AllocateBitrates(
if (bitrate_observer_configs_.empty())
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)
return ZeroRateAllocation();

View File

@ -14,10 +14,12 @@
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "rtc_base/bitrateallocationstrategy.h"
#include "rtc_base/sequenced_task_checker.h"
namespace webrtc {
@ -94,32 +96,35 @@ class BitrateAllocator {
// the list of added observers, a best guess is returned.
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:
// Note: All bitrates for member variables and methods are in bps.
struct ObserverConfig {
struct ObserverConfig : rtc::BitrateAllocationStrategy::TrackConfig {
ObserverConfig(BitrateAllocatorObserver* observer,
uint32_t min_bitrate_bps,
uint32_t max_bitrate_bps,
uint32_t pad_up_bitrate_bps,
bool enforce_min_bitrate,
std::string track_id)
: observer(observer),
min_bitrate_bps(min_bitrate_bps),
max_bitrate_bps(max_bitrate_bps),
: TrackConfig(min_bitrate_bps,
max_bitrate_bps,
enforce_min_bitrate,
track_id),
observer(observer),
pad_up_bitrate_bps(pad_up_bitrate_bps),
enforce_min_bitrate(enforce_min_bitrate),
allocated_bitrate_bps(-1),
media_ratio(1.0),
track_id(track_id) {}
media_ratio(1.0) {}
BitrateAllocatorObserver* observer;
uint32_t min_bitrate_bps;
uint32_t max_bitrate_bps;
uint32_t pad_up_bitrate_bps;
bool enforce_min_bitrate;
int64_t allocated_bitrate_bps;
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
@ -172,6 +177,8 @@ class BitrateAllocator {
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_min_bitrate_ RTC_GUARDED_BY(&sequenced_checker_);
std::unique_ptr<rtc::BitrateAllocationStrategy> bitrate_allocation_strategy_
RTC_GUARDED_BY(&sequenced_checker_);
};
} // namespace webrtc
#endif // CALL_BITRATE_ALLOCATOR_H_

View File

@ -214,6 +214,10 @@ class Call : public webrtc::Call,
void SetBitrateConfigMask(
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 OnTransportOverheadChanged(MediaType media,
@ -1007,6 +1011,24 @@ void Call::UpdateCurrentBitrateConfig(const rtc::Optional<int>& new_start) {
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) {
RTC_DCHECK_CALLED_SEQUENTIALLY(&configuration_sequence_checker_);
switch (media) {

View File

@ -24,6 +24,7 @@
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
#include "common_types.h" // NOLINT(build/include)
#include "rtc_base/bitrateallocationstrategy.h"
#include "rtc_base/networkroute.h"
#include "rtc_base/platform_file.h"
#include "rtc_base/socket.h"
@ -183,6 +184,10 @@ class Call {
virtual void SetBitrateConfigMask(
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
// media type going over different networks is supported, track the state
// for each stream separately. Right now it's global per media type.

View File

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

View File

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

View File

@ -595,6 +595,12 @@ void FakeCall::SetBitrateConfigMask(
// 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,
webrtc::NetworkState state) {
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;
void SetBitrateConfigMask(
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,
const rtc::NetworkRoute& network_route) override {}
void SignalChannelNetworkState(webrtc::MediaType media,

View File

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

View File

@ -107,6 +107,12 @@ class PacedSender : public Pacer {
size_t bytes,
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.
virtual int64_t QueueInMs() const;
@ -190,6 +196,7 @@ class PacedSender : public Pacer {
float pacing_factor_ RTC_GUARDED_BY(critsect_);
int64_t queue_time_limit RTC_GUARDED_BY(critsect_);
bool account_for_audio_ RTC_GUARDED_BY(critsect_);
};
} // namespace webrtc
#endif // MODULES_PACING_PACED_SENDER_H_

View File

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

View File

@ -498,6 +498,14 @@ class RtpPacketSender {
int64_t capture_time_ms,
size_t bytes,
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 {

View File

@ -1293,6 +1293,24 @@ RTCError PeerConnection::SetBitrate(const BitrateParameters& bitrate) {
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>
PeerConnection::GetRemoteAudioSSLCertificate() {
if (!session_) {

View File

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

View File

@ -113,6 +113,8 @@ rtc_source_set("rtc_base_approved_generic") {
"bind.h",
"bitbuffer.cc",
"bitbuffer.h",
"bitrateallocationstrategy.cc",
"bitrateallocationstrategy.h",
"buffer.h",
"bufferqueue.cc",
"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/RTCAudioTrack+Private.h",
"objc/Framework/Classes/PeerConnection/RTCAudioTrack.mm",
"objc/Framework/Classes/PeerConnection/RTCBitrateAllocationStrategy.mm",
"objc/Framework/Classes/PeerConnection/RTCConfiguration+Private.h",
"objc/Framework/Classes/PeerConnection/RTCConfiguration.mm",
"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/RTCAudioSource.h",
"objc/Framework/Headers/WebRTC/RTCAudioTrack.h",
"objc/Framework/Headers/WebRTC/RTCBitrateAllocationStrategy.h",
"objc/Framework/Headers/WebRTC/RTCConfiguration.h",
"objc/Framework/Headers/WebRTC/RTCDataChannel.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 =
rtc::Optional<rtc::IntervalRange>(*nativeIntervalRange);
}
return nativeConfig.release();
}

View File

@ -21,6 +21,7 @@
#import "RTCRtpReceiver+Private.h"
#import "RTCRtpSender+Private.h"
#import "RTCSessionDescription+Private.h"
#import "WebRTC/RTCBitrateAllocationStrategy.h"
#import "WebRTC/RTCLogging.h"
#include <memory>
@ -385,6 +386,15 @@ void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
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
maxSizeInBytes:(int64_t)maxSizeInBytes {
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 RTCSessionDescription;
@class RTCLegacyStatsReport;
@class RTCBitrateAllocationStrategy;
NS_ASSUME_NONNULL_BEGIN
@ -193,6 +194,13 @@ RTC_EXPORT
currentBitrateBps:(nullable NSNumber *)currentBitrateBps
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. */
- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
maxSizeInBytes:(int64_t)maxSizeInBytes;

View File

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