video_stream_adapter.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright 2020 The WebRTC Project Authors. All rights reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
  11. #define CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
  12. #include <memory>
  13. #include <utility>
  14. #include <vector>
  15. #include "absl/types/optional.h"
  16. #include "absl/types/variant.h"
  17. #include "api/adaptation/resource.h"
  18. #include "api/rtp_parameters.h"
  19. #include "api/video/video_adaptation_counters.h"
  20. #include "api/video/video_stream_encoder_observer.h"
  21. #include "call/adaptation/adaptation_constraint.h"
  22. #include "call/adaptation/degradation_preference_provider.h"
  23. #include "call/adaptation/video_source_restrictions.h"
  24. #include "call/adaptation/video_stream_input_state.h"
  25. #include "call/adaptation/video_stream_input_state_provider.h"
  26. #include "modules/video_coding/utility/quality_scaler.h"
  27. #include "rtc_base/experiments/balanced_degradation_settings.h"
  28. #include "rtc_base/thread_annotations.h"
  29. namespace webrtc {
  30. // The listener is responsible for carrying out the reconfiguration of the video
  31. // source such that the VideoSourceRestrictions are fulfilled.
  32. class VideoSourceRestrictionsListener {
  33. public:
  34. virtual ~VideoSourceRestrictionsListener();
  35. // The |restrictions| are filtered by degradation preference but not the
  36. // |adaptation_counters|, which are currently only reported for legacy stats
  37. // calculation purposes.
  38. virtual void OnVideoSourceRestrictionsUpdated(
  39. VideoSourceRestrictions restrictions,
  40. const VideoAdaptationCounters& adaptation_counters,
  41. rtc::scoped_refptr<Resource> reason,
  42. const VideoSourceRestrictions& unfiltered_restrictions) = 0;
  43. };
  44. class VideoStreamAdapter;
  45. extern const int kMinFrameRateFps;
  46. VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
  47. VideoSourceRestrictions source_restrictions,
  48. DegradationPreference degradation_preference);
  49. int GetHigherResolutionThan(int pixel_count);
  50. // Either represents the next VideoSourceRestrictions the VideoStreamAdapter
  51. // will take, or provides a Status code indicating the reason for not adapting
  52. // if the adaptation is not valid.
  53. class Adaptation final {
  54. public:
  55. enum class Status {
  56. // Applying this adaptation will have an effect. All other Status codes
  57. // indicate that adaptation is not possible and why.
  58. kValid,
  59. // Cannot adapt. The minimum or maximum adaptation has already been reached.
  60. // There are no more steps to take.
  61. kLimitReached,
  62. // Cannot adapt. The resolution or frame rate requested by a recent
  63. // adaptation has not yet been reflected in the input resolution or frame
  64. // rate; adaptation is refused to avoid "double-adapting".
  65. kAwaitingPreviousAdaptation,
  66. // Not enough input.
  67. kInsufficientInput,
  68. // Adaptation disabled via degradation preference.
  69. kAdaptationDisabled,
  70. // Adaptation up was rejected by a VideoAdaptationConstraint.
  71. kRejectedByConstraint,
  72. };
  73. static const char* StatusToString(Status status);
  74. Status status() const;
  75. const VideoStreamInputState& input_state() const;
  76. const VideoSourceRestrictions& restrictions() const;
  77. const VideoAdaptationCounters& counters() const;
  78. private:
  79. friend class VideoStreamAdapter;
  80. // Constructs with a valid adaptation. Status is kValid.
  81. Adaptation(int validation_id,
  82. VideoSourceRestrictions restrictions,
  83. VideoAdaptationCounters counters,
  84. VideoStreamInputState input_state);
  85. // Constructor when adaptation is not valid. Status MUST NOT be kValid.
  86. Adaptation(int validation_id, Status invalid_status);
  87. // An Adaptation can become invalidated if the state of VideoStreamAdapter is
  88. // modified before the Adaptation is applied. To guard against this, this ID
  89. // has to match VideoStreamAdapter::adaptation_validation_id_ when applied.
  90. // TODO(https://crbug.com/webrtc/11700): Remove the validation_id_.
  91. const int validation_id_;
  92. const Status status_;
  93. // Input state when adaptation was made.
  94. const VideoStreamInputState input_state_;
  95. const VideoSourceRestrictions restrictions_;
  96. const VideoAdaptationCounters counters_;
  97. };
  98. // Owns the VideoSourceRestriction for a single stream and is responsible for
  99. // adapting it up or down when told to do so. This class serves the following
  100. // purposes:
  101. // 1. Keep track of a stream's restrictions.
  102. // 2. Provide valid ways to adapt up or down the stream's restrictions.
  103. // 3. Modify the stream's restrictions in one of the valid ways.
  104. class VideoStreamAdapter {
  105. public:
  106. VideoStreamAdapter(VideoStreamInputStateProvider* input_state_provider,
  107. VideoStreamEncoderObserver* encoder_stats_observer);
  108. ~VideoStreamAdapter();
  109. VideoSourceRestrictions source_restrictions() const;
  110. const VideoAdaptationCounters& adaptation_counters() const;
  111. void ClearRestrictions();
  112. void AddRestrictionsListener(
  113. VideoSourceRestrictionsListener* restrictions_listener);
  114. void RemoveRestrictionsListener(
  115. VideoSourceRestrictionsListener* restrictions_listener);
  116. void AddAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
  117. void RemoveAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
  118. // TODO(hbos): Setting the degradation preference should not clear
  119. // restrictions! This is not defined in the spec and is unexpected, there is a
  120. // tiny risk that people would discover and rely on this behavior.
  121. void SetDegradationPreference(DegradationPreference degradation_preference);
  122. // Returns an adaptation that we are guaranteed to be able to apply, or a
  123. // status code indicating the reason why we cannot adapt.
  124. Adaptation GetAdaptationUp();
  125. Adaptation GetAdaptationDown();
  126. Adaptation GetAdaptationTo(const VideoAdaptationCounters& counters,
  127. const VideoSourceRestrictions& restrictions);
  128. // Tries to adapt the resolution one step. This is used for initial frame
  129. // dropping. Does nothing if the degradation preference is not BALANCED or
  130. // MAINTAIN_FRAMERATE. In the case of BALANCED, it will try twice to reduce
  131. // the resolution. If it fails twice it gives up.
  132. Adaptation GetAdaptDownResolution();
  133. // Updates source_restrictions() the Adaptation.
  134. void ApplyAdaptation(const Adaptation& adaptation,
  135. rtc::scoped_refptr<Resource> resource);
  136. struct RestrictionsWithCounters {
  137. VideoSourceRestrictions restrictions;
  138. VideoAdaptationCounters counters;
  139. };
  140. private:
  141. void BroadcastVideoRestrictionsUpdate(
  142. const VideoStreamInputState& input_state,
  143. const rtc::scoped_refptr<Resource>& resource);
  144. bool HasSufficientInputForAdaptation(const VideoStreamInputState& input_state)
  145. const RTC_RUN_ON(&sequence_checker_);
  146. using RestrictionsOrState =
  147. absl::variant<RestrictionsWithCounters, Adaptation::Status>;
  148. RestrictionsOrState GetAdaptationUpStep(
  149. const VideoStreamInputState& input_state) const
  150. RTC_RUN_ON(&sequence_checker_);
  151. RestrictionsOrState GetAdaptationDownStep(
  152. const VideoStreamInputState& input_state,
  153. const RestrictionsWithCounters& current_restrictions) const
  154. RTC_RUN_ON(&sequence_checker_);
  155. RestrictionsOrState GetAdaptDownResolutionStepForBalanced(
  156. const VideoStreamInputState& input_state) const
  157. RTC_RUN_ON(&sequence_checker_);
  158. RestrictionsOrState AdaptIfFpsDiffInsufficient(
  159. const VideoStreamInputState& input_state,
  160. const RestrictionsWithCounters& restrictions) const
  161. RTC_RUN_ON(&sequence_checker_);
  162. Adaptation GetAdaptationUp(const VideoStreamInputState& input_state) const
  163. RTC_RUN_ON(&sequence_checker_);
  164. Adaptation GetAdaptationDown(const VideoStreamInputState& input_state) const
  165. RTC_RUN_ON(&sequence_checker_);
  166. static RestrictionsOrState DecreaseResolution(
  167. const VideoStreamInputState& input_state,
  168. const RestrictionsWithCounters& current_restrictions);
  169. static RestrictionsOrState IncreaseResolution(
  170. const VideoStreamInputState& input_state,
  171. const RestrictionsWithCounters& current_restrictions);
  172. // Framerate methods are member functions because they need internal state
  173. // if the degradation preference is BALANCED.
  174. RestrictionsOrState DecreaseFramerate(
  175. const VideoStreamInputState& input_state,
  176. const RestrictionsWithCounters& current_restrictions) const
  177. RTC_RUN_ON(&sequence_checker_);
  178. RestrictionsOrState IncreaseFramerate(
  179. const VideoStreamInputState& input_state,
  180. const RestrictionsWithCounters& current_restrictions) const
  181. RTC_RUN_ON(&sequence_checker_);
  182. struct RestrictionsOrStateVisitor;
  183. Adaptation RestrictionsOrStateToAdaptation(
  184. RestrictionsOrState step_or_state,
  185. const VideoStreamInputState& input_state) const
  186. RTC_RUN_ON(&sequence_checker_);
  187. SequenceChecker sequence_checker_ RTC_GUARDED_BY(&sequence_checker_);
  188. // Gets the input state which is the basis of all adaptations.
  189. // Thread safe.
  190. VideoStreamInputStateProvider* input_state_provider_;
  191. // Used to signal when min pixel limit has been reached.
  192. VideoStreamEncoderObserver* const encoder_stats_observer_;
  193. // Decides the next adaptation target in DegradationPreference::BALANCED.
  194. const BalancedDegradationSettings balanced_settings_;
  195. // To guard against applying adaptations that have become invalidated, an
  196. // Adaptation that is applied has to have a matching validation ID.
  197. int adaptation_validation_id_ RTC_GUARDED_BY(&sequence_checker_);
  198. // When deciding the next target up or down, different strategies are used
  199. // depending on the DegradationPreference.
  200. // https://w3c.github.io/mst-content-hint/#dom-rtcdegradationpreference
  201. DegradationPreference degradation_preference_
  202. RTC_GUARDED_BY(&sequence_checker_);
  203. // Used to avoid adapting twice. Stores the resolution at the time of the last
  204. // adaptation.
  205. // TODO(hbos): Can we implement a more general "cooldown" mechanism of
  206. // resources intead? If we already have adapted it seems like we should wait
  207. // a while before adapting again, so that we are not acting on usage
  208. // measurements that are made obsolete/unreliable by an "ongoing" adaptation.
  209. struct AwaitingFrameSizeChange {
  210. AwaitingFrameSizeChange(bool pixels_increased, int frame_size);
  211. const bool pixels_increased;
  212. const int frame_size_pixels;
  213. };
  214. absl::optional<AwaitingFrameSizeChange> awaiting_frame_size_change_
  215. RTC_GUARDED_BY(&sequence_checker_);
  216. // The previous restrictions value. Starts as unrestricted.
  217. VideoSourceRestrictions last_video_source_restrictions_
  218. RTC_GUARDED_BY(&sequence_checker_);
  219. VideoSourceRestrictions last_filtered_restrictions_
  220. RTC_GUARDED_BY(&sequence_checker_);
  221. std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
  222. RTC_GUARDED_BY(&sequence_checker_);
  223. std::vector<AdaptationConstraint*> adaptation_constraints_
  224. RTC_GUARDED_BY(&sequence_checker_);
  225. RestrictionsWithCounters current_restrictions_
  226. RTC_GUARDED_BY(&sequence_checker_);
  227. };
  228. } // namespace webrtc
  229. #endif // CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_