blob: d4d9ff25b707c2a0e50780ca9a01cd3209463f01 [file] [log] [blame]
/*
* 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 VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
#define VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_
#include <memory>
#include "absl/types/optional.h"
#include "api/rtp_parameters.h"
#include "api/video/video_stream_encoder_observer.h"
#include "call/adaptation/encoder_settings.h"
#include "call/adaptation/resource.h"
#include "call/adaptation/video_source_restrictions.h"
#include "modules/video_coding/utility/quality_scaler.h"
#include "rtc_base/experiments/balanced_degradation_settings.h"
#include "video/adaptation/adaptation_counters.h"
namespace webrtc {
// 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:
enum class SetDegradationPreferenceResult {
kRestrictionsNotCleared,
kRestrictionsCleared,
};
enum class VideoInputMode {
kNoVideo,
kNormalVideo,
kScreenshareVideo,
};
enum class AdaptationAction {
kIncreaseResolution,
kDecreaseResolution,
kIncreaseFrameRate,
kDecreaseFrameRate,
};
// Describes an adaptation step: increasing or decreasing resolution or frame
// rate to a given value.
// TODO(https://crbug.com/webrtc/11393): Make these private implementation
// details, and expose something that allows you to inspect the
// VideoSourceRestrictions instead. The adaptation steps could be expressed as
// a graph, for instance.
struct AdaptationTarget {
AdaptationTarget(AdaptationAction action, int value);
// Which action the VideoSourceRestrictor needs to take.
const AdaptationAction action;
// Target pixel count or frame rate depending on |action|.
const int value;
// Allow this struct to be instantiated as an optional, even though it's in
// a private namespace.
friend class absl::optional<AdaptationTarget>;
};
VideoStreamAdapter();
~VideoStreamAdapter();
VideoSourceRestrictions source_restrictions() const;
const AdaptationCounters& adaptation_counters() const;
// TODO(hbos): Can we get rid of any external dependencies on
// BalancedDegradationPreference? How the adaptor generates possible next
// steps for adaptation should be an implementation detail. Can the relevant
// information be inferred from GetAdaptUpTarget()/GetAdaptDownTarget()?
const BalancedDegradationSettings& balanced_settings() const;
void ClearRestrictions();
// 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.
SetDegradationPreferenceResult SetDegradationPreference(
DegradationPreference degradation_preference);
// Returns a target that we are guaranteed to be able to adapt to, or null if
// adaptation is not desired or not possible.
absl::optional<AdaptationTarget> GetAdaptUpTarget(
const absl::optional<EncoderSettings>& encoder_settings,
absl::optional<uint32_t> encoder_target_bitrate_bps,
VideoInputMode input_mode,
int input_pixels,
int input_fps,
AdaptationObserverInterface::AdaptReason reason) const;
// TODO(https://crbug.com/webrtc/11393): Remove the dependency on
// |encoder_stats_observer| - simply checking which adaptation target is
// available should not have side-effects.
absl::optional<AdaptationTarget> GetAdaptDownTarget(
const absl::optional<EncoderSettings>& encoder_settings,
VideoInputMode input_mode,
int input_pixels,
int input_fps,
VideoStreamEncoderObserver* encoder_stats_observer) const;
// Applies the |target| to |source_restrictor_|.
// TODO(hbos): Delete ResourceListenerResponse!
ResourceListenerResponse ApplyAdaptationTarget(
const AdaptationTarget& target,
const absl::optional<EncoderSettings>& encoder_settings,
VideoInputMode input_mode,
int input_pixels,
int input_fps);
private:
class VideoSourceRestrictor;
// The input frame rate and resolution at the time of an adaptation in the
// direction described by |mode_| (up or down).
// TODO(https://crbug.com/webrtc/11393): Can this be renamed? Can this be
// merged with AdaptationTarget?
struct AdaptationRequest {
// The pixel count produced by the source at the time of the adaptation.
int input_pixel_count_;
// Framerate received from the source at the time of the adaptation.
int framerate_fps_;
// Indicates if request was to adapt up or down.
enum class Mode { kAdaptUp, kAdaptDown } mode_;
// This is a static method rather than an anonymous namespace function due
// to namespace visiblity.
static Mode GetModeFromAdaptationAction(AdaptationAction action);
};
// Reinterprets "balanced + screenshare" as "maintain-resolution".
// TODO(hbos): Don't do this. This is not what "balanced" means. If the
// application wants to maintain resolution it should set that degradation
// preference rather than depend on non-standard behaviors.
DegradationPreference EffectiveDegradationPreference(
VideoInputMode input_mode) const;
// Owner and modifier of the VideoSourceRestriction of this stream adaptor.
const std::unique_ptr<VideoSourceRestrictor> source_restrictor_;
// Decides the next adaptation target in DegradationPreference::BALANCED.
const BalancedDegradationSettings balanced_settings_;
// 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_;
// The input frame rate, resolution and adaptation direction of the last
// ApplyAdaptationTarget(). Used to avoid adapting twice if a recent
// adaptation has not had an effect on the input frame rate or resolution yet.
// 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.
absl::optional<AdaptationRequest> last_adaptation_request_;
};
} // namespace webrtc
#endif // VIDEO_ADAPTATION_VIDEO_STREAM_ADAPTER_H_