aboutsummaryrefslogtreecommitdiff
path: root/call/adaptation/resource_adaptation_processor.h
blob: cf1e187026aea04ec14fb7436f8692c15ce9b724 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 *  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_

#include <map>
#include <memory>
#include <vector>

#include "absl/types/optional.h"
#include "api/rtp_parameters.h"
#include "api/scoped_refptr.h"
#include "api/video/video_frame.h"
#include "api/video/video_stream_encoder_observer.h"
#include "call/adaptation/resource.h"
#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"
#include "rtc_base/synchronization/sequence_checker.h"

namespace webrtc {

// 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".
class ResourceAdaptationProcessor : public ResourceAdaptationProcessorInterface,
                                    public ResourceListener {
 public:
  ResourceAdaptationProcessor(
      VideoStreamInputStateProvider* input_state_provider,
      VideoStreamEncoderObserver* encoder_stats_observer);
  ~ResourceAdaptationProcessor() override;

  void InitializeOnResourceAdaptationQueue() override;

  // ResourceAdaptationProcessorInterface implementation.
  DegradationPreference degradation_preference() const override;
  DegradationPreference effective_degradation_preference() const override;

  void StartResourceAdaptation() override;
  void StopResourceAdaptation() override;
  void AddAdaptationListener(
      ResourceAdaptationProcessorListener* adaptation_listener) override;
  void RemoveAdaptationListener(
      ResourceAdaptationProcessorListener* adaptation_listener) override;
  void AddResource(rtc::scoped_refptr<Resource> resource) override;
  void RemoveResource(rtc::scoped_refptr<Resource> resource) override;

  void SetDegradationPreference(
      DegradationPreference degradation_preference) override;
  void SetIsScreenshare(bool is_screenshare) override;
  void ResetVideoSourceRestrictions() override;

  // ResourceListener implementation.
  // Triggers OnResourceUnderuse() or OnResourceOveruse().
  void OnResourceUsageStateMeasured(
      rtc::scoped_refptr<Resource> resource) override;

  // 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?
  void TriggerAdaptationDueToFrameDroppedDueToSize(
      rtc::scoped_refptr<Resource> reason_resource) override;

 private:
  bool HasSufficientInputForAdaptation(
      const VideoStreamInputState& input_state) const;

  // Performs the adaptation by getting the next target, applying it and
  // informing listeners of the new VideoSourceRestriction and adaptation
  // counters.
  void OnResourceUnderuse(rtc::scoped_refptr<Resource> reason_resource);
  void OnResourceOveruse(rtc::scoped_refptr<Resource> reason_resource);

  // 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.
  void MaybeUpdateVideoSourceRestrictions(rtc::scoped_refptr<Resource> reason);
  // Updates the number of times the resource has degraded based on the latest
  // degradation applied.
  void UpdateResourceDegradationCounts(rtc::scoped_refptr<Resource> resource);
  // Returns true if a Resource has been overused in the pass and is responsible
  // for creating a VideoSourceRestriction. The current algorithm counts the
  // number of times the resource caused an adaptation and allows adapting up
  // if that number is non-zero. This is consistent with how adaptation has
  // traditionally been handled.
  // TODO(crbug.com/webrtc/11553) Change this algorithm to look at the resources
  // restrictions rather than just the counters.
  bool IsResourceAllowedToAdaptUp(rtc::scoped_refptr<Resource> resource) const;

  webrtc::SequenceChecker sequence_checker_;
  bool is_resource_adaptation_enabled_ RTC_GUARDED_BY(sequence_checker_);
  // Input and output.
  VideoStreamInputStateProvider* const input_state_provider_
      RTC_GUARDED_BY(sequence_checker_);
  VideoStreamEncoderObserver* const encoder_stats_observer_
      RTC_GUARDED_BY(sequence_checker_);
  std::vector<ResourceAdaptationProcessorListener*> adaptation_listeners_
      RTC_GUARDED_BY(sequence_checker_);
  std::vector<rtc::scoped_refptr<Resource>> resources_
      RTC_GUARDED_BY(sequence_checker_);
  // Purely used for statistics, does not ensure mapped resources stay alive.
  std::map<const Resource*, int> adaptations_counts_by_resource_
      RTC_GUARDED_BY(sequence_checker_);
  // Adaptation strategy settings.
  DegradationPreference degradation_preference_
      RTC_GUARDED_BY(sequence_checker_);
  DegradationPreference effective_degradation_preference_
      RTC_GUARDED_BY(sequence_checker_);
  bool is_screenshare_ RTC_GUARDED_BY(sequence_checker_);
  // Responsible for generating and applying possible adaptations.
  const std::unique_ptr<VideoStreamAdapter> stream_adapter_
      RTC_GUARDED_BY(sequence_checker_);
  VideoSourceRestrictions last_reported_source_restrictions_
      RTC_GUARDED_BY(sequence_checker_);
  // 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.
  bool processing_in_progress_ RTC_GUARDED_BY(sequence_checker_);
};

}  // namespace webrtc

#endif  // CALL_ADAPTATION_RESOURCE_ADAPTATION_PROCESSOR_H_