2020-04-17 18:36:19 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright 2020 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_
|
|
|
|
|
|
2020-05-07 13:45:14 +02:00
|
|
|
#include <map>
|
2020-04-17 18:36:19 +02:00
|
|
|
#include <memory>
|
2020-05-28 16:22:42 +02:00
|
|
|
#include <string>
|
2020-06-11 10:45:29 +02:00
|
|
|
#include <utility>
|
2020-04-17 18:36:19 +02:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "absl/types/optional.h"
|
2020-06-03 09:24:06 +02:00
|
|
|
#include "api/adaptation/resource.h"
|
2020-04-17 18:36:19 +02:00
|
|
|
#include "api/rtp_parameters.h"
|
2020-05-11 16:29:22 +02:00
|
|
|
#include "api/scoped_refptr.h"
|
2020-06-03 09:21:34 +02:00
|
|
|
#include "api/task_queue/task_queue_base.h"
|
2020-04-17 18:36:19 +02:00
|
|
|
#include "api/video/video_frame.h"
|
|
|
|
|
#include "api/video/video_stream_encoder_observer.h"
|
2020-06-02 13:02:36 +02:00
|
|
|
#include "call/adaptation/adaptation_constraint.h"
|
|
|
|
|
#include "call/adaptation/adaptation_listener.h"
|
2020-04-17 18:36:19 +02:00
|
|
|
#include "call/adaptation/resource_adaptation_processor_interface.h"
|
|
|
|
|
#include "call/adaptation/video_source_restrictions.h"
|
|
|
|
|
#include "call/adaptation/video_stream_adapter.h"
|
|
|
|
|
#include "call/adaptation/video_stream_input_state.h"
|
|
|
|
|
#include "call/adaptation/video_stream_input_state_provider.h"
|
|
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2020-05-11 16:29:22 +02:00
|
|
|
// The Resource Adaptation Processor is responsible for reacting to resource
|
|
|
|
|
// usage measurements (e.g. overusing or underusing CPU). When a resource is
|
|
|
|
|
// overused the Processor is responsible for performing mitigations in order to
|
|
|
|
|
// consume less resources.
|
|
|
|
|
//
|
|
|
|
|
// Today we have one Processor per VideoStreamEncoder and the Processor is only
|
|
|
|
|
// capable of restricting resolution or frame rate of the encoded stream. In the
|
|
|
|
|
// future we should have a single Processor responsible for all encoded streams,
|
|
|
|
|
// and it should be capable of reconfiguring other things than just
|
|
|
|
|
// VideoSourceRestrictions (e.g. reduce render frame rate).
|
|
|
|
|
// See Resource-Adaptation hotlist:
|
|
|
|
|
// https://bugs.chromium.org/u/590058293/hotlists/Resource-Adaptation
|
|
|
|
|
//
|
|
|
|
|
// The ResourceAdaptationProcessor is single-threaded. It may be constructed on
|
|
|
|
|
// any thread but MUST subsequently be used and destroyed on a single sequence,
|
|
|
|
|
// i.e. the "resource adaptation task queue".
|
2020-04-17 18:36:19 +02:00
|
|
|
class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
|
|
|
|
|
public ResourceListener {
|
|
|
|
|
public:
|
|
|
|
|
ResourceAdaptationProcessor(
|
|
|
|
|
VideoStreamInputStateProvider* input_state_provider,
|
|
|
|
|
VideoStreamEncoderObserver* encoder_stats_observer);
|
|
|
|
|
~ResourceAdaptationProcessor() override;
|
|
|
|
|
|
2020-06-03 09:21:34 +02:00
|
|
|
void SetResourceAdaptationQueue(
|
|
|
|
|
TaskQueueBase* resource_adaptation_queue) override;
|
2020-05-11 16:29:22 +02:00
|
|
|
|
2020-04-17 18:36:19 +02:00
|
|
|
// ResourceAdaptationProcessorInterface implementation.
|
|
|
|
|
DegradationPreference degradation_preference() const override;
|
|
|
|
|
DegradationPreference effective_degradation_preference() const override;
|
|
|
|
|
|
|
|
|
|
void StartResourceAdaptation() override;
|
|
|
|
|
void StopResourceAdaptation() override;
|
2020-06-02 13:02:36 +02:00
|
|
|
void AddRestrictionsListener(
|
|
|
|
|
VideoSourceRestrictionsListener* restrictions_listener) override;
|
|
|
|
|
void RemoveRestrictionsListener(
|
|
|
|
|
VideoSourceRestrictionsListener* restrictions_listener) override;
|
2020-05-11 16:29:22 +02:00
|
|
|
void AddResource(rtc::scoped_refptr<Resource> resource) override;
|
2020-06-11 12:07:14 +02:00
|
|
|
std::vector<rtc::scoped_refptr<Resource>> GetResources() const override;
|
2020-05-11 16:29:22 +02:00
|
|
|
void RemoveResource(rtc::scoped_refptr<Resource> resource) override;
|
2020-06-02 13:02:36 +02:00
|
|
|
void AddAdaptationConstraint(
|
|
|
|
|
AdaptationConstraint* adaptation_constraint) override;
|
|
|
|
|
void RemoveAdaptationConstraint(
|
|
|
|
|
AdaptationConstraint* adaptation_constraint) override;
|
|
|
|
|
void AddAdaptationListener(AdaptationListener* adaptation_listener) override;
|
|
|
|
|
void RemoveAdaptationListener(
|
|
|
|
|
AdaptationListener* adaptation_listener) override;
|
2020-04-17 18:36:19 +02:00
|
|
|
|
|
|
|
|
void SetDegradationPreference(
|
|
|
|
|
DegradationPreference degradation_preference) override;
|
|
|
|
|
void SetIsScreenshare(bool is_screenshare) override;
|
|
|
|
|
void ResetVideoSourceRestrictions() override;
|
|
|
|
|
|
|
|
|
|
// ResourceListener implementation.
|
|
|
|
|
// Triggers OnResourceUnderuse() or OnResourceOveruse().
|
2020-06-03 09:21:34 +02:00
|
|
|
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
|
|
|
|
ResourceUsageState usage_state) override;
|
2020-04-17 18:36:19 +02:00
|
|
|
|
2020-04-30 10:13:29 +02:00
|
|
|
// May trigger 1-2 adaptations. It is meant to reduce resolution but this is
|
|
|
|
|
// not guaranteed. It may adapt frame rate, which does not address the issue.
|
|
|
|
|
// TODO(hbos): Can we get rid of this?
|
2020-04-17 18:36:19 +02:00
|
|
|
void TriggerAdaptationDueToFrameDroppedDueToSize(
|
2020-05-11 16:29:22 +02:00
|
|
|
rtc::scoped_refptr<Resource> reason_resource) override;
|
2020-04-17 18:36:19 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool HasSufficientInputForAdaptation(
|
|
|
|
|
const VideoStreamInputState& input_state) const;
|
|
|
|
|
|
2020-06-03 09:21:34 +02:00
|
|
|
// If resource usage measurements happens off the adaptation task queue, this
|
|
|
|
|
// class takes care of posting the measurement for the processor to handle it
|
|
|
|
|
// on the adaptation task queue.
|
|
|
|
|
class ResourceListenerDelegate : public rtc::RefCountInterface,
|
|
|
|
|
public ResourceListener {
|
|
|
|
|
public:
|
|
|
|
|
explicit ResourceListenerDelegate(ResourceAdaptationProcessor* processor);
|
|
|
|
|
|
|
|
|
|
void SetResourceAdaptationQueue(TaskQueueBase* resource_adaptation_queue);
|
|
|
|
|
void OnProcessorDestroyed();
|
|
|
|
|
|
|
|
|
|
// ResourceListener implementation.
|
|
|
|
|
void OnResourceUsageStateMeasured(rtc::scoped_refptr<Resource> resource,
|
|
|
|
|
ResourceUsageState usage_state) override;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
TaskQueueBase* resource_adaptation_queue_;
|
|
|
|
|
ResourceAdaptationProcessor* processor_
|
|
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-28 16:22:42 +02:00
|
|
|
enum class MitigationResult {
|
|
|
|
|
kDisabled,
|
|
|
|
|
kInsufficientInput,
|
2020-06-11 10:45:29 +02:00
|
|
|
kNotMostLimitedResource,
|
|
|
|
|
kSharedMostLimitedResource,
|
2020-05-28 16:22:42 +02:00
|
|
|
kRejectedByAdapter,
|
2020-06-02 13:02:36 +02:00
|
|
|
kRejectedByConstraint,
|
2020-05-28 16:22:42 +02:00
|
|
|
kAdaptationApplied,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct MitigationResultAndLogMessage {
|
|
|
|
|
MitigationResultAndLogMessage();
|
|
|
|
|
MitigationResultAndLogMessage(MitigationResult result, std::string message);
|
|
|
|
|
MitigationResult result;
|
|
|
|
|
std::string message;
|
|
|
|
|
};
|
|
|
|
|
|
2020-04-17 18:36:19 +02:00
|
|
|
// Performs the adaptation by getting the next target, applying it and
|
|
|
|
|
// informing listeners of the new VideoSourceRestriction and adaptation
|
|
|
|
|
// counters.
|
2020-05-28 16:22:42 +02:00
|
|
|
MitigationResultAndLogMessage OnResourceUnderuse(
|
|
|
|
|
rtc::scoped_refptr<Resource> reason_resource);
|
|
|
|
|
MitigationResultAndLogMessage OnResourceOveruse(
|
|
|
|
|
rtc::scoped_refptr<Resource> reason_resource);
|
2020-04-17 18:36:19 +02:00
|
|
|
|
|
|
|
|
// Needs to be invoked any time |degradation_preference_| or |is_screenshare_|
|
|
|
|
|
// changes to ensure |effective_degradation_preference_| is up-to-date.
|
|
|
|
|
void MaybeUpdateEffectiveDegradationPreference();
|
|
|
|
|
// If the filtered source restrictions are different than
|
|
|
|
|
// |last_reported_source_restrictions_|, inform the listeners.
|
2020-05-11 16:29:22 +02:00
|
|
|
void MaybeUpdateVideoSourceRestrictions(rtc::scoped_refptr<Resource> reason);
|
2020-06-11 10:45:29 +02:00
|
|
|
|
|
|
|
|
void UpdateResourceLimitations(
|
|
|
|
|
rtc::scoped_refptr<Resource> reason_resource,
|
|
|
|
|
const VideoStreamAdapter::RestrictionsWithCounters&
|
|
|
|
|
peek_next_restrictions) RTC_RUN_ON(resource_adaptation_queue_);
|
|
|
|
|
|
|
|
|
|
// Searches |adaptation_limits_by_resources_| for each resource with the
|
|
|
|
|
// highest total adaptation counts. Adaptation up may only occur if the
|
|
|
|
|
// resource performing the adaptation is the only most limited resource. This
|
|
|
|
|
// function returns the list of all most limited resources as well as the
|
|
|
|
|
// corresponding adaptation of that resource.
|
|
|
|
|
std::pair<std::vector<rtc::scoped_refptr<Resource>>, VideoAdaptationCounters>
|
|
|
|
|
FindMostLimitedResources() const RTC_RUN_ON(resource_adaptation_queue_);
|
2020-04-17 18:36:19 +02:00
|
|
|
|
2020-06-03 09:21:34 +02:00
|
|
|
TaskQueueBase* resource_adaptation_queue_;
|
|
|
|
|
rtc::scoped_refptr<ResourceListenerDelegate> resource_listener_delegate_;
|
|
|
|
|
bool is_resource_adaptation_enabled_
|
|
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-04-17 18:36:19 +02:00
|
|
|
// Input and output.
|
2020-05-11 16:29:22 +02:00
|
|
|
VideoStreamInputStateProvider* const input_state_provider_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-11 16:29:22 +02:00
|
|
|
VideoStreamEncoderObserver* const encoder_stats_observer_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-06-02 13:02:36 +02:00
|
|
|
std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-11 16:29:22 +02:00
|
|
|
std::vector<rtc::scoped_refptr<Resource>> resources_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-06-02 13:02:36 +02:00
|
|
|
std::vector<AdaptationConstraint*> adaptation_constraints_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-06-02 13:02:36 +02:00
|
|
|
std::vector<AdaptationListener*> adaptation_listeners_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-11 16:29:22 +02:00
|
|
|
// Purely used for statistics, does not ensure mapped resources stay alive.
|
2020-06-11 10:45:29 +02:00
|
|
|
std::map<rtc::scoped_refptr<Resource>, VideoAdaptationCounters>
|
|
|
|
|
adaptation_limits_by_resources_
|
|
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-04-17 18:36:19 +02:00
|
|
|
// Adaptation strategy settings.
|
2020-05-11 16:29:22 +02:00
|
|
|
DegradationPreference degradation_preference_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-11 16:29:22 +02:00
|
|
|
DegradationPreference effective_degradation_preference_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
|
|
|
|
bool is_screenshare_ RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-04-17 18:36:19 +02:00
|
|
|
// Responsible for generating and applying possible adaptations.
|
2020-05-11 16:29:22 +02:00
|
|
|
const std::unique_ptr<VideoStreamAdapter> stream_adapter_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-11 16:29:22 +02:00
|
|
|
VideoSourceRestrictions last_reported_source_restrictions_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-05-28 16:22:42 +02:00
|
|
|
// Keeps track of previous mitigation results per resource since the last
|
|
|
|
|
// successful adaptation. Used to avoid RTC_LOG spam.
|
|
|
|
|
std::map<Resource*, MitigationResult> previous_mitigation_results_
|
2020-06-03 09:21:34 +02:00
|
|
|
RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-04-28 12:24:33 +02:00
|
|
|
// Prevents recursion.
|
|
|
|
|
//
|
|
|
|
|
// This is used to prevent triggering resource adaptation in the process of
|
|
|
|
|
// already handling resouce adaptation, since that could cause the same states
|
|
|
|
|
// to be modified in unexpected ways. Example:
|
|
|
|
|
//
|
|
|
|
|
// Resource::OnResourceUsageStateMeasured() ->
|
|
|
|
|
// ResourceAdaptationProcessor::OnResourceOveruse() ->
|
|
|
|
|
// Resource::OnAdaptationApplied() ->
|
|
|
|
|
// Resource::OnResourceUsageStateMeasured() ->
|
|
|
|
|
// ResourceAdaptationProcessor::OnResourceOveruse() // Boom, not allowed.
|
2020-06-03 09:21:34 +02:00
|
|
|
bool processing_in_progress_ RTC_GUARDED_BY(resource_adaptation_queue_);
|
2020-04-17 18:36:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace webrtc
|
|
|
|
|
|
|
|
|
|
#endif // CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_
|