blob: f3044138cac8c378632d5bbd69d8ae7d1f26b40d [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 Aloncde8ab22019-03-20 11:56:20 +0100109 // Number of streamed controlled by |this|.
110 virtual size_t StreamCount() const = 0;
111
Elad Alonde3360e2019-03-06 21:14:54 +0100112 // If this method returns true, the encoder is free to drop frames for
113 // instance in an effort to uphold encoding bitrate.
114 // If this return false, the encoder must not drop any frames unless:
115 // 1. Requested to do so via Vp8FrameConfig.drop_frame
116 // 2. The frame to be encoded is requested to be a keyframe
Elad Alon6cdbf3f2019-05-08 10:02:46 +0200117 // 3. The encoder detected a large overshoot and decided to drop and then
Elad Alonde3360e2019-03-06 21:14:54 +0100118 // re-encode the image at a low bitrate. In this case the encoder should
Elad Alon1f28c282019-05-07 21:31:21 +0200119 // call OnFrameDropped() once to indicate drop, and then call
Elad Alonde3360e2019-03-06 21:14:54 +0100120 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 11:56:20 +0100121 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100122
Elad Alon979c4422019-04-17 12:53:08 +0200123 // New target bitrate for a stream (each entry in
124 // |bitrates_bps| is for another temporal layer).
Elad Aloncde8ab22019-03-20 11:56:20 +0100125 virtual void OnRatesUpdated(size_t stream_index,
126 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 21:14:54 +0100127 int framerate_fps) = 0;
128
Elad Alonfb087812019-05-02 23:25:34 +0200129 // Called by the encoder before encoding a frame. Returns a set of overrides
130 // the controller wishes to enact in the encoder's configuration.
131 // If a value is not overridden, previous overrides are still in effect.
Elad Alon5cf39032019-06-12 11:29:04 +0200132 // However, if |Vp8EncoderConfig::reset_previous_configuration_overrides|
133 // is set to |true|, all previous overrides are reset.
Elad Alonfb087812019-05-02 23:25:34 +0200134 virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100135
Elad Alon979c4422019-04-17 12:53:08 +0200136 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 21:14:54 +0100137 // The timestamp may be used as both a time and a unique identifier, and so
138 // the caller must make sure no two frames use the same timestamp.
139 // The timestamp uses a 90kHz RTP clock.
140 // After calling this method, first call the actual encoder with the provided
141 // frame configuration, and then OnEncodeDone() below.
Elad Alon979c4422019-04-17 12:53:08 +0200142 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
143 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100144
145 // Called after the encode step is done. |rtp_timestamp| must match the
Elad Alon162a0392019-04-23 15:33:59 +0200146 // parameter use in the NextFrameConfig() call.
Elad Alonde3360e2019-03-06 21:14:54 +0100147 // |is_keyframe| must be true iff the encoder decided to encode this frame as
148 // a keyframe.
Elad Alon979c4422019-04-17 12:53:08 +0200149 // If |info| is not null, the encoder may update |info| with codec specific
150 // data such as temporal id. |qp| should indicate the frame-level QP this
151 // frame was encoded at. If the encoder does not support extracting this, |qp|
152 // should be set to 0.
Elad Aloncde8ab22019-03-20 11:56:20 +0100153 virtual void OnEncodeDone(size_t stream_index,
154 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 21:14:54 +0100155 size_t size_bytes,
156 bool is_keyframe,
157 int qp,
158 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100159
Elad Alon6796ec22019-04-15 10:07:50 +0200160 // Called when a frame is dropped by the encoder.
161 virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;
162
Elad Aloncde8ab22019-03-20 11:56:20 +0100163 // Called by the encoder when the packet loss rate changes.
164 // |packet_loss_rate| runs between 0.0 (no loss) and 1.0 (everything lost).
165 virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;
166
167 // Called by the encoder when the round trip time changes.
168 virtual void OnRttUpdate(int64_t rtt_ms) = 0;
Elad Alon6c371ca2019-04-04 12:28:51 +0200169
170 // Called when a loss notification is received.
171 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 12:48:06 +0200172 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100173};
174
175// Interface for a factory of Vp8FrameBufferController instances.
176class Vp8FrameBufferControllerFactory {
177 public:
178 virtual ~Vp8FrameBufferControllerFactory() = default;
179
Elad Alond9c900f2019-06-17 14:36:27 +0200180 // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.)
Elad Alone8df4822019-06-26 11:51:04 +0200181 virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0;
Elad Alond9c900f2019-06-17 14:36:27 +0200182
Elad Alone8df4822019-06-26 11:51:04 +0200183 // Create a Vp8FrameBufferController instance.
Elad Alon45befc52019-07-02 11:20:09 +0200184 // TODO(bugs.webrtc.org/10769): Update downstream projects, then remove
185 // version without |fec_controller_override| and make the other version
186 // pure-virtual.
187 // (In theory, if neither version is overridden, stack overflow would occur.
188 // In practice, all subclasses override at least one version, and following
189 // the update of downstream projects, only one pure-virtual version will
190 // remain.)
Elad Alona2795842019-06-07 23:10:00 +0200191 virtual std::unique_ptr<Vp8FrameBufferController> Create(
192 const VideoCodec& codec,
Elad Alon45befc52019-07-02 11:20:09 +0200193 const VideoEncoder::Settings& settings) {
194 return Create(codec, settings, nullptr);
195 }
196 virtual std::unique_ptr<Vp8FrameBufferController> Create(
197 const VideoCodec& codec,
198 const VideoEncoder::Settings& settings,
199 FecControllerOverride* fec_controller_override) {
200 return Create(codec, settings);
201 }
Elad Alonde3360e2019-03-06 21:14:54 +0100202};
203
204} // namespace webrtc
205
206#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_