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

media / gpu / windows / video_rate_control_wrapper.h [blame]

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_GPU_WINDOWS_VIDEO_RATE_CONTROL_WRAPPER_H_
#define MEDIA_GPU_WINDOWS_VIDEO_RATE_CONTROL_WRAPPER_H_

#include <cstdint>
#include <memory>

#include "media/base/media_log.h"
#include "media/gpu/media_gpu_export.h"
#include "media/video/video_encode_accelerator.h"

namespace media {

// These constants come from svc and codec spec.
constexpr size_t kMaxTemporalLayers = 8;
constexpr size_t kMaxSpatialLayers = 4;
constexpr size_t kMaxLayers = kMaxTemporalLayers * kMaxSpatialLayers;

// VideoRateControlWrapper is a base class for computing
// proper quantization param for each frame.
class VideoRateControlWrapper {
 public:
  // RateControlConfig is a type of helper for passing configs
  // to codec-specific rate controller.
  struct RateControlConfig {
    RateControlConfig();
    ~RateControlConfig();

    RateControlConfig(const RateControlConfig&);
    RateControlConfig& operator=(const RateControlConfig&);

    // Frame size.
    int width = 0;
    int height = 0;
    // Quantizer parameter,the range is 0-63.
    int max_quantizer = 0;
    int min_quantizer = 0;
    // Target_bandwidth is in kbps.
    int64_t target_bandwidth = 0;
    // Frame rate.
    double framerate = 0.0f;
    // Content type, camera or display.
    VideoEncodeAccelerator::Config::ContentType content_type =
        VideoEncodeAccelerator::Config::ContentType::kCamera;
    // Target bitrate for svc layers.
    int layer_target_bitrate[kMaxLayers] = {};
    // Rate decimator for temporal layers.
    int ts_rate_decimator[kMaxTemporalLayers] = {};
    // Number of spatial layers.
    int ss_number_layers = 0;
    // Number of temporal layers.
    int ts_number_layers = 0;
    // Quantizer parameter for svc layers.
    int max_quantizers[kMaxLayers] = {};
    int min_quantizers[kMaxLayers] = {};
    // Scaling factor parameters for spatial layers.
    int scaling_factor_num[kMaxSpatialLayers] = {};
    int scaling_factor_den[kMaxSpatialLayers] = {};
    // If defined, the H.264 BRC uses fixed QP difference between layers. Should
    // not be defined for other SW BRCs.
    std::optional<int> fixed_delta_qp;
  };

  // FrameParams is used for passing frame params.
  struct FrameParams {
    enum class FrameType { kKeyFrame, kInterFrame };
    FrameType frame_type = FrameType::kKeyFrame;
    int spatial_layer_id = 0;
    int temporal_layer_id = 0;
    unsigned int timestamp = 0;
  };

  virtual ~VideoRateControlWrapper() = default;
  virtual void UpdateRateControl(const RateControlConfig& config) = 0;
  // ComputeQP() returns qp table index and the range is up to the codec.
  virtual int ComputeQP(const FrameParams& frame_params) = 0;
  // GetLoopfilterLevel() is only available for VP9, others return -1.
  virtual int GetLoopfilterLevel() const = 0;
  // Feedback to rate control with the size of current encoded frame.
  virtual void PostEncodeUpdate(uint64_t encoded_frame_size,
                                const FrameParams& frame_params) = 0;
};

// VideoRateControlWrapperInternal is an interface for creating
// codec-specific rate controller.
template <typename RateControlConfigType,
          typename RateCtrlType,
          typename FrameParamsType>
class VideoRateControlWrapperInternal : public VideoRateControlWrapper {
 public:
  // Creates VideoRateControlWrapper implementation.
  static std::unique_ptr<VideoRateControlWrapperInternal> Create(
      const RateControlConfig& config) {
    auto impl = RateCtrlType::Create(ConvertControlConfig(config));
    if (!impl) {
      DLOG(ERROR) << "Failed creating video RateController";
      return nullptr;
    }
    return std::make_unique<VideoRateControlWrapperInternal>(std::move(impl));
  }
  VideoRateControlWrapperInternal() = default;
  explicit VideoRateControlWrapperInternal(std::unique_ptr<RateCtrlType> impl)
      : impl_(std::move(impl)) {}
  ~VideoRateControlWrapperInternal() override = default;
  void UpdateRateControl(const RateControlConfig& config) override {
    DCHECK(impl_);
    impl_->UpdateRateControl(ConvertControlConfig(config));
  }
  int ComputeQP(const FrameParams& frame_params) override {
    DCHECK(impl_);
    impl_->ComputeQP(ConvertFrameParams(frame_params));
    return impl_->GetQP();
  }
  int GetLoopfilterLevel() const override;
  void PostEncodeUpdate(uint64_t encoded_frame_size,
                        const FrameParams& frame_params) override;

 private:
  // "ConvertControlConfig" and "ConvertFrameParams" are used for passing
  // parameters to impl_, which should be specialized when the template is
  // instantiated.
  static RateControlConfigType ConvertControlConfig(
      const RateControlConfig& config);
  static FrameParamsType ConvertFrameParams(const FrameParams& frame_params);

  std::unique_ptr<RateCtrlType> impl_;
};

}  // namespace media

#endif  // MEDIA_GPU_WINDOWS_VIDEO_RATE_CONTROL_WRAPPER_H_