blob: 94e08a9aeaa3235333e5a1e82a4f1ee4e14b6e54 [file] [log] [blame]
Elad Alonde3360e2019-03-06 21:14:54 +01001/*
2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
12#define API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_
13
Elad Alonfb087812019-05-02 23:25:34 +020014#include <array>
Elad Aloncde8ab22019-03-20 11:56:20 +010015#include <memory>
Elad Alonde3360e2019-03-06 21:14:54 +010016#include <vector>
17
Elad Alon6c371ca2019-04-04 12:28:51 +020018#include "absl/types/optional.h"
Elad Alon7e00c672019-06-28 18:12:15 +020019#include "api/fec_controller_override.h"
Elad Aloncde8ab22019-03-20 11:56:20 +010020#include "api/video_codecs/video_codec.h"
Elad Alon6c371ca2019-04-04 12:28:51 +020021#include "api/video_codecs/video_encoder.h"
Elad Alonde3360e2019-03-06 21:14:54 +010022#include "api/video_codecs/vp8_frame_config.h"
23
24namespace webrtc {
25
26// Some notes on the prerequisites of the TemporalLayers interface.
27// * Vp8FrameBufferController is not thread safe, synchronization is the
28// caller's responsibility.
29// * The encoder is assumed to encode all frames in order, and callbacks to
Elad Alon979c4422019-04-17 12:53:08 +020030// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
Elad Alonde3360e2019-03-06 21:14:54 +010031//
32// This means that in the case of pipelining encoders, it is OK to have a chain
33// of calls such as this:
Elad Alon162a0392019-04-23 15:33:59 +020034// - NextFrameConfig(timestampA)
35// - NextFrameConfig(timestampB)
Elad Alonde3360e2019-03-06 21:14:54 +010036// - PopulateCodecSpecific(timestampA, ...)
Elad Alon162a0392019-04-23 15:33:59 +020037// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010038// - OnEncodeDone(timestampA, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020039// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010040// - OnEncodeDone(timestampB, 0, ...)
41// - OnEncodeDone(timestampC, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020042// Note that NextFrameConfig() for a new frame can happen before
Elad Alon979c4422019-04-17 12:53:08 +020043// OnEncodeDone() for a previous one, but calls themselves must be both
Elad Alonde3360e2019-03-06 21:14:54 +010044// synchronized (e.g. run on a task queue) and in order (per type).
Elad Alon979c4422019-04-17 12:53:08 +020045//
46// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
47// context is not very meaningful).
Elad Alonde3360e2019-03-06 21:14:54 +010048
49struct CodecSpecificInfo;
50
Elad Alonfb087812019-05-02 23:25:34 +020051// Each member represents an override of the VPX configuration if the optional
52// value is set.
Elad Alonde3360e2019-03-06 21:14:54 +010053struct Vp8EncoderConfig {
Elad Alonfb087812019-05-02 23:25:34 +020054 struct TemporalLayerConfig {
55 bool operator!=(const TemporalLayerConfig& other) const {
56 return ts_number_layers != other.ts_number_layers ||
57 ts_target_bitrate != other.ts_target_bitrate ||
58 ts_rate_decimator != other.ts_rate_decimator ||
59 ts_periodicity != other.ts_periodicity ||
60 ts_layer_id != other.ts_layer_id;
61 }
Elad Alonde3360e2019-03-06 21:14:54 +010062
Elad Alonfb087812019-05-02 23:25:34 +020063 static constexpr size_t kMaxPeriodicity = 16;
64 static constexpr size_t kMaxLayers = 5;
Elad Alonde3360e2019-03-06 21:14:54 +010065
Elad Alonfb087812019-05-02 23:25:34 +020066 // Number of active temporal layers. Set to 0 if not used.
67 uint32_t ts_number_layers;
68
69 // Arrays of length |ts_number_layers|, indicating (cumulative) target
70 // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given
71 // layer) for each active temporal layer, starting with temporal id 0.
72 std::array<uint32_t, kMaxLayers> ts_target_bitrate;
73 std::array<uint32_t, kMaxLayers> ts_rate_decimator;
74
75 // The periodicity of the temporal pattern. Set to 0 if not used.
76 uint32_t ts_periodicity;
77
78 // Array of length |ts_periodicity| indicating the sequence of temporal id's
79 // to assign to incoming frames.
80 std::array<uint32_t, kMaxPeriodicity> ts_layer_id;
81 };
82
83 absl::optional<TemporalLayerConfig> temporal_layer_config;
Elad Alonde3360e2019-03-06 21:14:54 +010084
85 // Target bitrate, in bps.
Elad Alonfb087812019-05-02 23:25:34 +020086 absl::optional<uint32_t> rc_target_bitrate;
Elad Alonde3360e2019-03-06 21:14:54 +010087
Elad Alonfb087812019-05-02 23:25:34 +020088 // Clamp QP to max. Use 0 to disable clamping.
89 absl::optional<uint32_t> rc_max_quantizer;
Elad Alon544dece2019-04-25 14:24:36 +020090
Elad Alonfb087812019-05-02 23:25:34 +020091 // Error resilience mode.
92 absl::optional<uint32_t> g_error_resilient;
Elad Alon5cf39032019-06-12 11:29:04 +020093
94 // If set to true, all previous configuration overrides should be reset.
95 bool reset_previous_configuration_overrides = false;
Elad Alonde3360e2019-03-06 21:14:54 +010096};
97
98// This interface defines a way of delegating the logic of buffer management.
Elad Aloncde8ab22019-03-20 11:56:20 +010099// Multiple streams may be controlled by a single controller, demuxing between
100// them using stream_index.
Elad Alonde3360e2019-03-06 21:14:54 +0100101class Vp8FrameBufferController {
102 public:
103 virtual ~Vp8FrameBufferController() = default;
104
Elad Alonfb087812019-05-02 23:25:34 +0200105 // Set limits on QP.
106 // The limits are suggestion-only; the controller is allowed to exceed them.
107 virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0;
108
Elad Alon7e00c672019-06-28 18:12:15 +0200109 // Set a FecControllerOverride, through which the bandwidth allocation
110 // decisions made by FecController may be overridden.
111 // TODO(bugs.webrtc.org/10769): Update downstream projects, then make
112 // this pure-virtual.
113 virtual void SetFecControllerOverride(
114 FecControllerOverride* fec_controller_override) {}
115
Elad Aloncde8ab22019-03-20 11:56:20 +0100116 // Number of streamed controlled by |this|.
117 virtual size_t StreamCount() const = 0;
118
Elad Alonde3360e2019-03-06 21:14:54 +0100119 // If this method returns true, the encoder is free to drop frames for
120 // instance in an effort to uphold encoding bitrate.
121 // If this return false, the encoder must not drop any frames unless:
122 // 1. Requested to do so via Vp8FrameConfig.drop_frame
123 // 2. The frame to be encoded is requested to be a keyframe
Elad Alon6cdbf3f2019-05-08 10:02:46 +0200124 // 3. The encoder detected a large overshoot and decided to drop and then
Elad Alonde3360e2019-03-06 21:14:54 +0100125 // re-encode the image at a low bitrate. In this case the encoder should
Elad Alon1f28c282019-05-07 21:31:21 +0200126 // call OnFrameDropped() once to indicate drop, and then call
Elad Alonde3360e2019-03-06 21:14:54 +0100127 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 11:56:20 +0100128 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100129
Elad Alon979c4422019-04-17 12:53:08 +0200130 // New target bitrate for a stream (each entry in
131 // |bitrates_bps| is for another temporal layer).
Elad Aloncde8ab22019-03-20 11:56:20 +0100132 virtual void OnRatesUpdated(size_t stream_index,
133 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 21:14:54 +0100134 int framerate_fps) = 0;
135
Elad Alonfb087812019-05-02 23:25:34 +0200136 // Called by the encoder before encoding a frame. Returns a set of overrides
137 // the controller wishes to enact in the encoder's configuration.
138 // If a value is not overridden, previous overrides are still in effect.
Elad Alon5cf39032019-06-12 11:29:04 +0200139 // However, if |Vp8EncoderConfig::reset_previous_configuration_overrides|
140 // is set to |true|, all previous overrides are reset.
Elad Alonfb087812019-05-02 23:25:34 +0200141 virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100142
Elad Alon979c4422019-04-17 12:53:08 +0200143 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 21:14:54 +0100144 // The timestamp may be used as both a time and a unique identifier, and so
145 // the caller must make sure no two frames use the same timestamp.
146 // The timestamp uses a 90kHz RTP clock.
147 // After calling this method, first call the actual encoder with the provided
148 // frame configuration, and then OnEncodeDone() below.
Elad Alon979c4422019-04-17 12:53:08 +0200149 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
150 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100151
152 // Called after the encode step is done. |rtp_timestamp| must match the
Elad Alon162a0392019-04-23 15:33:59 +0200153 // parameter use in the NextFrameConfig() call.
Elad Alonde3360e2019-03-06 21:14:54 +0100154 // |is_keyframe| must be true iff the encoder decided to encode this frame as
155 // a keyframe.
Elad Alon979c4422019-04-17 12:53:08 +0200156 // If |info| is not null, the encoder may update |info| with codec specific
157 // data such as temporal id. |qp| should indicate the frame-level QP this
158 // frame was encoded at. If the encoder does not support extracting this, |qp|
159 // should be set to 0.
Elad Aloncde8ab22019-03-20 11:56:20 +0100160 virtual void OnEncodeDone(size_t stream_index,
161 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 21:14:54 +0100162 size_t size_bytes,
163 bool is_keyframe,
164 int qp,
165 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100166
Elad Alon6796ec22019-04-15 10:07:50 +0200167 // Called when a frame is dropped by the encoder.
168 virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;
169
Elad Aloncde8ab22019-03-20 11:56:20 +0100170 // Called by the encoder when the packet loss rate changes.
171 // |packet_loss_rate| runs between 0.0 (no loss) and 1.0 (everything lost).
172 virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;
173
174 // Called by the encoder when the round trip time changes.
175 virtual void OnRttUpdate(int64_t rtt_ms) = 0;
Elad Alon6c371ca2019-04-04 12:28:51 +0200176
177 // Called when a loss notification is received.
178 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 12:48:06 +0200179 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100180};
181
182// Interface for a factory of Vp8FrameBufferController instances.
183class Vp8FrameBufferControllerFactory {
184 public:
185 virtual ~Vp8FrameBufferControllerFactory() = default;
186
Elad Alond9c900f2019-06-17 14:36:27 +0200187 // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.)
Elad Alone8df4822019-06-26 11:51:04 +0200188 virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0;
Elad Alond9c900f2019-06-17 14:36:27 +0200189
Elad Alone8df4822019-06-26 11:51:04 +0200190 // Create a Vp8FrameBufferController instance.
Elad Alona2795842019-06-07 23:10:00 +0200191 virtual std::unique_ptr<Vp8FrameBufferController> Create(
192 const VideoCodec& codec,
Elad Alone8df4822019-06-26 11:51:04 +0200193 const VideoEncoder::Settings& settings) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100194};
195
196} // namespace webrtc
197
198#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_