webrtc_m130/call/adaptation/resource_adaptation_processor.h
Henrik Boström b04b2a1719 Initial version of ResourceAdaptationProcessor and friends.
This CL adds Resource, ResourceConsumer, ResourceConsumerConfiguration
and ResourceAdaptationProcessor and implements the algorithm outlined
in
https://docs.google.com/presentation/d/13jyqCWNpIa873iKT6yDuB5Q5ma-c0CvxBpX--0tCclY/edit?usp=sharing.

Simply put, if any resource (such as "CPU") is overusing, the most
expensive consumer (e.g. encoded stream) is adapted one step down.
If all resources are underusing, the least expensive consumer is
adapted one step up.

The current resources, consumers and configurations are all fakes;
this CL has no effect on the current adaptation algorithms used in
practise, but it lays down the foundation for future work in this
area.

Bug: webrtc:11167, webrtc:11168, webrtc:11169
Change-Id: I4054ec7728a52a49e137eee6fa67fa27debd9254
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161237
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30053}
2019-12-10 15:31:43 +00:00

119 lines
4.5 KiB
C++

/*
* Copyright 2019 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 CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_
#define CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_
#include <memory>
#include <utility>
#include <vector>
#include "absl/types/optional.h"
#include "call/adaptation/resource.h"
#include "call/adaptation/resource_consumer.h"
#include "call/adaptation/resource_consumer_configuration.h"
namespace webrtc {
struct ConsumerConfigurationPair {
ConsumerConfigurationPair(ResourceConsumer* consumer,
ResourceConsumerConfiguration* configuration);
ResourceConsumer* consumer;
ResourceConsumerConfiguration* configuration;
};
// Given a set of Resources, ResourceConsumers and
// ResourceConsumerConfigurations, the processor calculates which consumer, if
// any, should be reconfigured and how, in order to adapt to resource
// constraints.
// Example: "CPU" is a resource, a video stream being encoded is a consumer
// and the encoder setting (e.g. VP8/720p/30fps) is a configuration.
//
// A resource can be "overused", "stable" or "underused". The processor
// maximises quality without overusing any resource as follows:
// 1. If we are "overusing" on any resource, find the most expensive consumer
// and adapt it one step "down".
// 2. If we are "underusing" on all resources, find the least expensive consumer
// and adapt it one step "up".
//
// The expensiveness of a consumer is the expensiveness of its current
// configuration and the cost of a configuration is estimated based on pixels
// per second. How a consumer can be reconfigured in terms of one step "up" or
// "down" is expressed as a graph: each configuration has a set of "upper"
// neighbors and "lower" neighbors. When there are multiple options, neighbors
// are chosen based on configuration preferences.
//
// See FindNextConfiguration().
//
// This class owns all resources, consumers and configurations. As long as it is
// alive, raw pointers to these are safe to use.
class ResourceAdaptationProcessor {
public:
const std::vector<std::unique_ptr<Resource>>& resources() const {
return resources_;
}
const std::vector<std::unique_ptr<ResourceConsumerConfiguration>>&
configurations() const {
return configurations_;
}
const std::vector<std::unique_ptr<ResourceConsumer>>& consumers() const {
return consumers_;
}
// Takes on ownership of the argument. A raw pointer is returned to the object
// for convenience; it is valid for the lifetime of the
// ResourceAdaptationProcessor.
// T = any subclass of Resource
template <typename T>
T* AddResource(std::unique_ptr<T> resource) {
T* resource_ptr = resource.get();
resources_.push_back(std::move(resource));
return resource_ptr;
}
// T = any subclass of ResourceConsumerConfiguration
template <typename T>
T* AddConfiguration(std::unique_ptr<T> configuration) {
T* configuration_ptr = configuration.get();
configurations_.push_back(std::move(configuration));
return configuration_ptr;
}
// T = any subclass of ResourceConsumer
template <typename T>
T* AddConsumer(std::unique_ptr<T> consumer) {
T* consumer_ptr = consumer.get();
consumers_.push_back(std::move(consumer));
return consumer_ptr;
}
// Based on the current state of the resources and consumers, finds the
// consumer that should be reconfigured up or down in order to maximies
// quality without overusing any resources, as described in
// ResourceAdaptationProcessor's class description.
//
// When this is used in a real system, care needs to be taken for how often
// FindNextConfiguration() is called. There may be a delay between
// reconfiguring a consumer and the desired effects being observed on resource
// usage.
absl::optional<ConsumerConfigurationPair> FindNextConfiguration();
private:
ResourceConsumer* FindMostExpensiveConsumerThatCanBeAdaptedDown();
ResourceConsumer* FindLeastExpensiveConsumerThatCanBeAdaptedUp();
std::vector<std::unique_ptr<Resource>> resources_;
std::vector<std::unique_ptr<ResourceConsumerConfiguration>> configurations_;
std::vector<std::unique_ptr<ResourceConsumer>> consumers_;
};
} // namespace webrtc
#endif // CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_