summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/api/video_codecs/vp8_frame_buffer_controller.h
blob: fc494f72931cba7de127f9fbc721e42e66489c90 (plain)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
 *  Copyright (c) 2019 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 API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
#define API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_

#include <array>
#include <memory>
#include <vector>

#include "absl/types/optional.h"
#include "api/fec_controller_override.h"
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/video_encoder.h"
#include "api/video_codecs/vp8_frame_config.h"

namespace webrtc {

// Some notes on the prerequisites of the TemporalLayers interface.
// * Vp8FrameBufferController is not thread safe, synchronization is the
//   caller's responsibility.
// * The encoder is assumed to encode all frames in order, and callbacks to
//   PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
//
// This means that in the case of pipelining encoders, it is OK to have a chain
// of calls such as this:
// - NextFrameConfig(timestampA)
// - NextFrameConfig(timestampB)
// - PopulateCodecSpecific(timestampA, ...)
// - NextFrameConfig(timestampC)
// - OnEncodeDone(timestampA, 1234, ...)
// - NextFrameConfig(timestampC)
// - OnEncodeDone(timestampB, 0, ...)
// - OnEncodeDone(timestampC, 1234, ...)
// Note that NextFrameConfig() for a new frame can happen before
// OnEncodeDone() for a previous one, but calls themselves must be both
// synchronized (e.g. run on a task queue) and in order (per type).
//
// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
// context is not very meaningful).

struct CodecSpecificInfo;

// Each member represents an override of the VPX configuration if the optional
// value is set.
struct Vp8EncoderConfig {
  struct TemporalLayerConfig {
    bool operator!=(const TemporalLayerConfig& other) const {
      return ts_number_layers != other.ts_number_layers ||
             ts_target_bitrate != other.ts_target_bitrate ||
             ts_rate_decimator != other.ts_rate_decimator ||
             ts_periodicity != other.ts_periodicity ||
             ts_layer_id != other.ts_layer_id;
    }

    static constexpr size_t kMaxPeriodicity = 16;
    static constexpr size_t kMaxLayers = 5;

    // Number of active temporal layers. Set to 0 if not used.
    uint32_t ts_number_layers;

    // Arrays of length `ts_number_layers`, indicating (cumulative) target
    // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given
    // layer) for each active temporal layer, starting with temporal id 0.
    std::array<uint32_t, kMaxLayers> ts_target_bitrate;
    std::array<uint32_t, kMaxLayers> ts_rate_decimator;

    // The periodicity of the temporal pattern. Set to 0 if not used.
    uint32_t ts_periodicity;

    // Array of length `ts_periodicity` indicating the sequence of temporal id's
    // to assign to incoming frames.
    std::array<uint32_t, kMaxPeriodicity> ts_layer_id;
  };

  absl::optional<TemporalLayerConfig> temporal_layer_config;

  // Target bitrate, in bps.
  absl::optional<uint32_t> rc_target_bitrate;

  // Clamp QP to max. Use 0 to disable clamping.
  absl::optional<uint32_t> rc_max_quantizer;

  // Error resilience mode.
  absl::optional<uint32_t> g_error_resilient;

  // If set to true, all previous configuration overrides should be reset.
  bool reset_previous_configuration_overrides = false;
};

// This interface defines a way of delegating the logic of buffer management.
// Multiple streams may be controlled by a single controller, demuxing between
// them using stream_index.
class Vp8FrameBufferController {
 public:
  virtual ~Vp8FrameBufferController() = default;

  // Set limits on QP.
  // The limits are suggestion-only; the controller is allowed to exceed them.
  virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0;

  // Number of streamed controlled by `this`.
  virtual size_t StreamCount() const = 0;

  // If this method returns true, the encoder is free to drop frames for
  // instance in an effort to uphold encoding bitrate.
  // If this return false, the encoder must not drop any frames unless:
  //  1. Requested to do so via Vp8FrameConfig.drop_frame
  //  2. The frame to be encoded is requested to be a keyframe
  //  3. The encoder detected a large overshoot and decided to drop and then
  //     re-encode the image at a low bitrate. In this case the encoder should
  //     call OnFrameDropped() once to indicate drop, and then call
  //     OnEncodeDone() again when the frame has actually been encoded.
  virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;

  // New target bitrate for a stream (each entry in
  // `bitrates_bps` is for another temporal layer).
  virtual void OnRatesUpdated(size_t stream_index,
                              const std::vector<uint32_t>& bitrates_bps,
                              int framerate_fps) = 0;

  // Called by the encoder before encoding a frame. Returns a set of overrides
  // the controller wishes to enact in the encoder's configuration.
  // If a value is not overridden, previous overrides are still in effect.
  // However, if `Vp8EncoderConfig::reset_previous_configuration_overrides`
  // is set to `true`, all previous overrides are reset.
  virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;

  // Returns the recommended VP8 encode flags needed.
  // The timestamp may be used as both a time and a unique identifier, and so
  // the caller must make sure no two frames use the same timestamp.
  // The timestamp uses a 90kHz RTP clock.
  // After calling this method, first call the actual encoder with the provided
  // frame configuration, and then OnEncodeDone() below.
  virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
                                         uint32_t rtp_timestamp) = 0;

  // Called after the encode step is done. `rtp_timestamp` must match the
  // parameter use in the NextFrameConfig() call.
  // `is_keyframe` must be true iff the encoder decided to encode this frame as
  // a keyframe.
  // If `info` is not null, the encoder may update `info` with codec specific
  // data such as temporal id. `qp` should indicate the frame-level QP this
  // frame was encoded at. If the encoder does not support extracting this, `qp`
  // should be set to 0.
  virtual void OnEncodeDone(size_t stream_index,
                            uint32_t rtp_timestamp,
                            size_t size_bytes,
                            bool is_keyframe,
                            int qp,
                            CodecSpecificInfo* info) = 0;

  // Called when a frame is dropped by the encoder.
  virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;

  // Called by the encoder when the packet loss rate changes.
  // `packet_loss_rate` runs between 0.0 (no loss) and 1.0 (everything lost).
  virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;

  // Called by the encoder when the round trip time changes.
  virtual void OnRttUpdate(int64_t rtt_ms) = 0;

  // Called when a loss notification is received.
  virtual void OnLossNotification(
      const VideoEncoder::LossNotification& loss_notification) = 0;
};

// Interface for a factory of Vp8FrameBufferController instances.
class Vp8FrameBufferControllerFactory {
 public:
  virtual ~Vp8FrameBufferControllerFactory() = default;

  // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.)
  virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0;

  // Create a Vp8FrameBufferController instance.
  virtual std::unique_ptr<Vp8FrameBufferController> Create(
      const VideoCodec& codec,
      const VideoEncoder::Settings& settings,
      FecControllerOverride* fec_controller_override) = 0;
};

}  // namespace webrtc

#endif  // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_