webrtc_m130/call/adaptation/video_stream_adapter.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

270 lines
11 KiB
C
Raw Normal View History

/*
* 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"
[Adaptation] Introduce VideoStreamInputState and its Provider. This CL is part of the Call-Level Adaptation Processing design doc: https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing The "input state" of a VideoStream, needed for adaptation and decision-making, are: source resolution and frame rate, codec type and min pixels per frame (based on encoder scaling settings). These values are modified on the encoder queue of the VideoStreamEncoder. But in order to unblock call-level adaptation processing, where adaptation and decision making happens off the encoder queue, a snapshot of the input states need to be available at point of processing: introducing the VideoStreamInputState. In this CL, the VideoStreamInputStateProvider is added to provide input state snapshots across threads based on input from VideoStreamEncoder and VideoStreamEncoderObserver. The input state's HasInputFrameSizeAndFramesPerSecond() can now be DCHECKed inside the VideoStreamAdapter in favor of having less Adaptation::Status codes. Whether input is "sufficient" for adaptation is now the responsibility of the Processor. (Goal: adapter is purely a Adaptation generator and apply-er.) Somewhat tangental, this CL also deletes VideoStreamEncoder-specific methods from ResourceAdaptationProcessorInterface making them an implementation detail of ResourceAdaptationProcessor. In a future CL, the "processor" will be split up into a "processor" part and a "video stream encoder resource manager" part - more on that later. Bug: webrtc:11172 Change-Id: Id9b158f569db0140b75360aaf0f7e2e28fb924f4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172928 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31098}
2020-04-17 12:10:59 +02:00
#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/system/no_unique_address.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;
};
[Adaptation] Resource::IsAdaptationUpAllowed() for IsBitrateConstrained. This CL is part of the Call-Level Adaptation Processing design doc: https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing The VideoStreamAdapter is currently responsible for aborting and not providing adaptations if we are bitrate constrained (kIsBitrateConstrained). Whether or not we are bitrate constrained is clearly a resource question and should be phrased as such. By moving this logic to Resource::IsAdaptationUpAllowed(), the VideoStreamAdapter can continue to be thread-agnostic when a future CL introduces a "processing queue", and the VideoStreamAdapter can be simplified: it returns Adaptations even if we are constrained (but we refuse to Apply them any resource rejects it). This CL adds new Resource classes as inner classes of ResourceAdaptationProcessor that take on the responsibility of kIsBitrateConstrained logic: PreventIncreaseResolutionDueToBitrateResource and PreventAdaptUpInBalancedResource. A third class, PreventAdaptUpDueToActiveCounts, also allows us to move adaptation-aborting logic. This piece of code appears to be about not adapting up if we’re already at the highest setting, which would be VideoStreamAdapter responsibility (covered by Adaptation::Status::kLimitReached), but it is actually more complicated than that: the active_counts_ care about "reason", so it is really about "is this resource type OK with you adapting up?". We should probably rewrite this code in the future, but for now it is moved to an inner class of ResourceAdaptationProcessor. Other misc changes: - ApplyDegradationPreference is moved to video_stream_adapter.[h/cc] and renamed "Filter". - OnResourceOveruse/Underuse now use Resource* as the reason instead of AdaptReason. In a future CL, the processor will be split into a "processor" part and a "video stream encoder resource manager" part. Only the manager needs to know about AdaptReason since this is only used for |active_counts_| and we want to get rid of it as much as possible as it is not future-proof. Bug: webrtc:11172 Change-Id: I2eba9ec3d717f7024c451aeb14635fe759551318 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172930 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31099}
2020-04-17 13:48:21 +02:00
class VideoStreamAdapter;
extern const int kMinFrameRateFps;
[Adaptation] Resource::IsAdaptationUpAllowed() for IsBitrateConstrained. This CL is part of the Call-Level Adaptation Processing design doc: https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing The VideoStreamAdapter is currently responsible for aborting and not providing adaptations if we are bitrate constrained (kIsBitrateConstrained). Whether or not we are bitrate constrained is clearly a resource question and should be phrased as such. By moving this logic to Resource::IsAdaptationUpAllowed(), the VideoStreamAdapter can continue to be thread-agnostic when a future CL introduces a "processing queue", and the VideoStreamAdapter can be simplified: it returns Adaptations even if we are constrained (but we refuse to Apply them any resource rejects it). This CL adds new Resource classes as inner classes of ResourceAdaptationProcessor that take on the responsibility of kIsBitrateConstrained logic: PreventIncreaseResolutionDueToBitrateResource and PreventAdaptUpInBalancedResource. A third class, PreventAdaptUpDueToActiveCounts, also allows us to move adaptation-aborting logic. This piece of code appears to be about not adapting up if we’re already at the highest setting, which would be VideoStreamAdapter responsibility (covered by Adaptation::Status::kLimitReached), but it is actually more complicated than that: the active_counts_ care about "reason", so it is really about "is this resource type OK with you adapting up?". We should probably rewrite this code in the future, but for now it is moved to an inner class of ResourceAdaptationProcessor. Other misc changes: - ApplyDegradationPreference is moved to video_stream_adapter.[h/cc] and renamed "Filter". - OnResourceOveruse/Underuse now use Resource* as the reason instead of AdaptReason. In a future CL, the processor will be split into a "processor" part and a "video stream encoder resource manager" part. Only the manager needs to know about AdaptReason since this is only used for |active_counts_| and we want to get rid of it as much as possible as it is not future-proof. Bug: webrtc:11172 Change-Id: I2eba9ec3d717f7024c451aeb14635fe759551318 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172930 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31099}
2020-04-17 13:48:21 +02:00
VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
VideoSourceRestrictions source_restrictions,
DegradationPreference degradation_preference);
int GetLowerResolutionThan(int pixel_count);
[Adaptation] Resource::IsAdaptationUpAllowed() for IsBitrateConstrained. This CL is part of the Call-Level Adaptation Processing design doc: https://docs.google.com/document/d/1ZyC26yOCknrrcYa839ZWLxD6o6Gig5A3lVTh4E41074/edit?usp=sharing The VideoStreamAdapter is currently responsible for aborting and not providing adaptations if we are bitrate constrained (kIsBitrateConstrained). Whether or not we are bitrate constrained is clearly a resource question and should be phrased as such. By moving this logic to Resource::IsAdaptationUpAllowed(), the VideoStreamAdapter can continue to be thread-agnostic when a future CL introduces a "processing queue", and the VideoStreamAdapter can be simplified: it returns Adaptations even if we are constrained (but we refuse to Apply them any resource rejects it). This CL adds new Resource classes as inner classes of ResourceAdaptationProcessor that take on the responsibility of kIsBitrateConstrained logic: PreventIncreaseResolutionDueToBitrateResource and PreventAdaptUpInBalancedResource. A third class, PreventAdaptUpDueToActiveCounts, also allows us to move adaptation-aborting logic. This piece of code appears to be about not adapting up if we’re already at the highest setting, which would be VideoStreamAdapter responsibility (covered by Adaptation::Status::kLimitReached), but it is actually more complicated than that: the active_counts_ care about "reason", so it is really about "is this resource type OK with you adapting up?". We should probably rewrite this code in the future, but for now it is moved to an inner class of ResourceAdaptationProcessor. Other misc changes: - ApplyDegradationPreference is moved to video_stream_adapter.[h/cc] and renamed "Filter". - OnResourceOveruse/Underuse now use Resource* as the reason instead of AdaptReason. In a future CL, the processor will be split into a "processor" part and a "video stream encoder resource manager" part. Only the manager needs to know about AdaptReason since this is only used for |active_counts_| and we want to get rid of it as much as possible as it is not future-proof. Bug: webrtc:11172 Change-Id: I2eba9ec3d717f7024c451aeb14635fe759551318 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/172930 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#31099}
2020-04-17 13:48:21 +02:00
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.
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
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,
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
// 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);
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
Status status() const;
const VideoStreamInputState& input_state() const;
const VideoSourceRestrictions& restrictions() const;
const VideoAdaptationCounters& counters() const;
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
private:
friend class VideoStreamAdapter;
// Constructs with a valid adaptation. Status is kValid.
Adaptation(int validation_id,
VideoSourceRestrictions restrictions,
VideoAdaptationCounters counters,
VideoStreamInputState input_state);
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
// Constructor when adaptation is not valid. Status MUST NOT be kValid.
Adaptation(int validation_id, Status invalid_status);
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
// 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_.
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
const int validation_id_;
const Status status_;
// Input state when adaptation was made.
const VideoStreamInputState input_state_;
const VideoSourceRestrictions restrictions_;
const VideoAdaptationCounters counters_;
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
};
// 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);
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
// 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;
};
static absl::optional<uint32_t> GetSingleActiveLayerPixels(
const VideoCodec& codec);
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_);
RTC_NO_UNIQUE_ADDRESS 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_;
[Adaptation] Refactor AdaptationTarget. Peek next restrictions. This CL introduces the Adaptation class used by VideoStreamRestrictor. This refactors the AdaptationTarget, AdaptationTargetOrReason, CannotAdaptReason and AdaptationAction. What is publicly exposed is simply a Status code. If it's kValid then we can adapt, otherwise the status code describes why we can't adapt (just like CannotAdaptReason prior to this CL). This means AdaptationTargetOrReason is no longer needed. Target+reason are merged. The other classes are renamed and moved and put in the private namespace of Adaptation: Only the VideoStreamAdapter (now a friend class of Adaptation) and its inner class VideoSourceRestrictor needs to know how to execute the adaptation. Publicly, you can now tell the effects of the adaptation without applying it with PeekNextRestrictions() - both current and next steps are described in terms of VideoSourceRestrictions. The rest are hidden. This would make it possible, in the future, for a Resource to accept or reject a proposed Adaptation by examining the resulting frame rate and resolution described by the resulting restrictions. E.g. even if we are not overusing bandwidth at the moment, the BW resource can prevent us from applying a restriction that would exceed the BW limit before we apply it. This CL also moves input to a SetInput() method, and Increase/Decrease methods of VideoSourceRestrictor are made private in favor of ApplyAdaptationSteps(). Bug: webrtc:11393 Change-Id: Ie5e2181836ab3713b8021c1a152694ca745aeb0d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170111 Commit-Queue: Henrik Boström <hbos@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#30794}
2020-03-14 10:53:57 +01:00
// 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_