123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- /*
- * 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_VIDEO_STREAM_ADAPTER_H_
- #define CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
- #include <memory>
- #include <utility>
- #include <vector>
- #include "absl/types/optional.h"
- #include "absl/types/variant.h"
- #include "api/adaptation/resource.h"
- #include "api/rtp_parameters.h"
- #include "api/video/video_adaptation_counters.h"
- #include "api/video/video_stream_encoder_observer.h"
- #include "call/adaptation/adaptation_constraint.h"
- #include "call/adaptation/degradation_preference_provider.h"
- #include "call/adaptation/video_source_restrictions.h"
- #include "call/adaptation/video_stream_input_state.h"
- #include "call/adaptation/video_stream_input_state_provider.h"
- #include "modules/video_coding/utility/quality_scaler.h"
- #include "rtc_base/experiments/balanced_degradation_settings.h"
- #include "rtc_base/thread_annotations.h"
- namespace webrtc {
- // The listener is responsible for carrying out the reconfiguration of the video
- // source such that the VideoSourceRestrictions are fulfilled.
- class VideoSourceRestrictionsListener {
- public:
- virtual ~VideoSourceRestrictionsListener();
- // The |restrictions| are filtered by degradation preference but not the
- // |adaptation_counters|, which are currently only reported for legacy stats
- // calculation purposes.
- virtual void OnVideoSourceRestrictionsUpdated(
- VideoSourceRestrictions restrictions,
- const VideoAdaptationCounters& adaptation_counters,
- rtc::scoped_refptr<Resource> reason,
- const VideoSourceRestrictions& unfiltered_restrictions) = 0;
- };
- class VideoStreamAdapter;
- extern const int kMinFrameRateFps;
- VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
- VideoSourceRestrictions source_restrictions,
- DegradationPreference degradation_preference);
- int GetHigherResolutionThan(int pixel_count);
- // Either represents the next VideoSourceRestrictions the VideoStreamAdapter
- // will take, or provides a Status code indicating the reason for not adapting
- // if the adaptation is not valid.
- class Adaptation final {
- public:
- enum class Status {
- // Applying this adaptation will have an effect. All other Status codes
- // indicate that adaptation is not possible and why.
- kValid,
- // Cannot adapt. The minimum or maximum adaptation has already been reached.
- // There are no more steps to take.
- kLimitReached,
- // Cannot adapt. The resolution or frame rate requested by a recent
- // adaptation has not yet been reflected in the input resolution or frame
- // rate; adaptation is refused to avoid "double-adapting".
- kAwaitingPreviousAdaptation,
- // Not enough input.
- kInsufficientInput,
- // Adaptation disabled via degradation preference.
- kAdaptationDisabled,
- // Adaptation up was rejected by a VideoAdaptationConstraint.
- kRejectedByConstraint,
- };
- static const char* StatusToString(Status status);
- Status status() const;
- const VideoStreamInputState& input_state() const;
- const VideoSourceRestrictions& restrictions() const;
- const VideoAdaptationCounters& counters() const;
- private:
- friend class VideoStreamAdapter;
- // Constructs with a valid adaptation. Status is kValid.
- Adaptation(int validation_id,
- VideoSourceRestrictions restrictions,
- VideoAdaptationCounters counters,
- VideoStreamInputState input_state);
- // Constructor when adaptation is not valid. Status MUST NOT be kValid.
- Adaptation(int validation_id, Status invalid_status);
- // An Adaptation can become invalidated if the state of VideoStreamAdapter is
- // modified before the Adaptation is applied. To guard against this, this ID
- // has to match VideoStreamAdapter::adaptation_validation_id_ when applied.
- // TODO(https://crbug.com/webrtc/11700): Remove the validation_id_.
- const int validation_id_;
- const Status status_;
- // Input state when adaptation was made.
- const VideoStreamInputState input_state_;
- const VideoSourceRestrictions restrictions_;
- const VideoAdaptationCounters counters_;
- };
- // Owns the VideoSourceRestriction for a single stream and is responsible for
- // adapting it up or down when told to do so. This class serves the following
- // purposes:
- // 1. Keep track of a stream's restrictions.
- // 2. Provide valid ways to adapt up or down the stream's restrictions.
- // 3. Modify the stream's restrictions in one of the valid ways.
- class VideoStreamAdapter {
- public:
- VideoStreamAdapter(VideoStreamInputStateProvider* input_state_provider,
- VideoStreamEncoderObserver* encoder_stats_observer);
- ~VideoStreamAdapter();
- VideoSourceRestrictions source_restrictions() const;
- const VideoAdaptationCounters& adaptation_counters() const;
- void ClearRestrictions();
- void AddRestrictionsListener(
- VideoSourceRestrictionsListener* restrictions_listener);
- void RemoveRestrictionsListener(
- VideoSourceRestrictionsListener* restrictions_listener);
- void AddAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
- void RemoveAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
- // TODO(hbos): Setting the degradation preference should not clear
- // restrictions! This is not defined in the spec and is unexpected, there is a
- // tiny risk that people would discover and rely on this behavior.
- void SetDegradationPreference(DegradationPreference degradation_preference);
- // Returns an adaptation that we are guaranteed to be able to apply, or a
- // status code indicating the reason why we cannot adapt.
- Adaptation GetAdaptationUp();
- Adaptation GetAdaptationDown();
- Adaptation GetAdaptationTo(const VideoAdaptationCounters& counters,
- const VideoSourceRestrictions& restrictions);
- // Tries to adapt the resolution one step. This is used for initial frame
- // dropping. Does nothing if the degradation preference is not BALANCED or
- // MAINTAIN_FRAMERATE. In the case of BALANCED, it will try twice to reduce
- // the resolution. If it fails twice it gives up.
- Adaptation GetAdaptDownResolution();
- // Updates source_restrictions() the Adaptation.
- void ApplyAdaptation(const Adaptation& adaptation,
- rtc::scoped_refptr<Resource> resource);
- struct RestrictionsWithCounters {
- VideoSourceRestrictions restrictions;
- VideoAdaptationCounters counters;
- };
- private:
- void BroadcastVideoRestrictionsUpdate(
- const VideoStreamInputState& input_state,
- const rtc::scoped_refptr<Resource>& resource);
- bool HasSufficientInputForAdaptation(const VideoStreamInputState& input_state)
- const RTC_RUN_ON(&sequence_checker_);
- using RestrictionsOrState =
- absl::variant<RestrictionsWithCounters, Adaptation::Status>;
- RestrictionsOrState GetAdaptationUpStep(
- const VideoStreamInputState& input_state) const
- RTC_RUN_ON(&sequence_checker_);
- RestrictionsOrState GetAdaptationDownStep(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& current_restrictions) const
- RTC_RUN_ON(&sequence_checker_);
- RestrictionsOrState GetAdaptDownResolutionStepForBalanced(
- const VideoStreamInputState& input_state) const
- RTC_RUN_ON(&sequence_checker_);
- RestrictionsOrState AdaptIfFpsDiffInsufficient(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& restrictions) const
- RTC_RUN_ON(&sequence_checker_);
- Adaptation GetAdaptationUp(const VideoStreamInputState& input_state) const
- RTC_RUN_ON(&sequence_checker_);
- Adaptation GetAdaptationDown(const VideoStreamInputState& input_state) const
- RTC_RUN_ON(&sequence_checker_);
- static RestrictionsOrState DecreaseResolution(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& current_restrictions);
- static RestrictionsOrState IncreaseResolution(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& current_restrictions);
- // Framerate methods are member functions because they need internal state
- // if the degradation preference is BALANCED.
- RestrictionsOrState DecreaseFramerate(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& current_restrictions) const
- RTC_RUN_ON(&sequence_checker_);
- RestrictionsOrState IncreaseFramerate(
- const VideoStreamInputState& input_state,
- const RestrictionsWithCounters& current_restrictions) const
- RTC_RUN_ON(&sequence_checker_);
- struct RestrictionsOrStateVisitor;
- Adaptation RestrictionsOrStateToAdaptation(
- RestrictionsOrState step_or_state,
- const VideoStreamInputState& input_state) const
- RTC_RUN_ON(&sequence_checker_);
- SequenceChecker sequence_checker_ RTC_GUARDED_BY(&sequence_checker_);
- // Gets the input state which is the basis of all adaptations.
- // Thread safe.
- VideoStreamInputStateProvider* input_state_provider_;
- // Used to signal when min pixel limit has been reached.
- VideoStreamEncoderObserver* const encoder_stats_observer_;
- // Decides the next adaptation target in DegradationPreference::BALANCED.
- const BalancedDegradationSettings balanced_settings_;
- // To guard against applying adaptations that have become invalidated, an
- // Adaptation that is applied has to have a matching validation ID.
- int adaptation_validation_id_ RTC_GUARDED_BY(&sequence_checker_);
- // When deciding the next target up or down, different strategies are used
- // depending on the DegradationPreference.
- // https://w3c.github.io/mst-content-hint/#dom-rtcdegradationpreference
- DegradationPreference degradation_preference_
- RTC_GUARDED_BY(&sequence_checker_);
- // Used to avoid adapting twice. Stores the resolution at the time of the last
- // adaptation.
- // TODO(hbos): Can we implement a more general "cooldown" mechanism of
- // resources intead? If we already have adapted it seems like we should wait
- // a while before adapting again, so that we are not acting on usage
- // measurements that are made obsolete/unreliable by an "ongoing" adaptation.
- struct AwaitingFrameSizeChange {
- AwaitingFrameSizeChange(bool pixels_increased, int frame_size);
- const bool pixels_increased;
- const int frame_size_pixels;
- };
- absl::optional<AwaitingFrameSizeChange> awaiting_frame_size_change_
- RTC_GUARDED_BY(&sequence_checker_);
- // The previous restrictions value. Starts as unrestricted.
- VideoSourceRestrictions last_video_source_restrictions_
- RTC_GUARDED_BY(&sequence_checker_);
- VideoSourceRestrictions last_filtered_restrictions_
- RTC_GUARDED_BY(&sequence_checker_);
- std::vector<VideoSourceRestrictionsListener*> restrictions_listeners_
- RTC_GUARDED_BY(&sequence_checker_);
- std::vector<AdaptationConstraint*> adaptation_constraints_
- RTC_GUARDED_BY(&sequence_checker_);
- RestrictionsWithCounters current_restrictions_
- RTC_GUARDED_BY(&sequence_checker_);
- };
- } // namespace webrtc
- #endif // CALL_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
|