blob: fc494f72931cba7de127f9fbc721e42e66489c90 [file] [log] [blame]
Elad Alonde3360e2019-03-06 20:14:541/*
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 21:25:3414#include <array>
Elad Aloncde8ab22019-03-20 10:56:2015#include <memory>
Elad Alonde3360e2019-03-06 20:14:5416#include <vector>
17
Elad Alon6c371ca2019-04-04 10:28:5118#include "absl/types/optional.h"
Elad Alon7e00c672019-06-28 16:12:1519#include "api/fec_controller_override.h"
Elad Aloncde8ab22019-03-20 10:56:2020#include "api/video_codecs/video_codec.h"
Elad Alon6c371ca2019-04-04 10:28:5121#include "api/video_codecs/video_encoder.h"
Elad Alonde3360e2019-03-06 20:14:5422#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 Alon979c4426a2019-04-17 10:53:0830// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
Elad Alonde3360e2019-03-06 20:14:5431//
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 13:33:5934// - NextFrameConfig(timestampA)
35// - NextFrameConfig(timestampB)
Elad Alonde3360e2019-03-06 20:14:5436// - PopulateCodecSpecific(timestampA, ...)
Elad Alon162a0392019-04-23 13:33:5937// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 20:14:5438// - OnEncodeDone(timestampA, 1234, ...)
Elad Alon162a0392019-04-23 13:33:5939// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 20:14:5440// - OnEncodeDone(timestampB, 0, ...)
41// - OnEncodeDone(timestampC, 1234, ...)
Elad Alon162a0392019-04-23 13:33:5942// Note that NextFrameConfig() for a new frame can happen before
Elad Alon979c4426a2019-04-17 10:53:0843// OnEncodeDone() for a previous one, but calls themselves must be both
Elad Alonde3360e2019-03-06 20:14:5444// synchronized (e.g. run on a task queue) and in order (per type).
Elad Alon979c4426a2019-04-17 10:53:0845//
46// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
47// context is not very meaningful).
Elad Alonde3360e2019-03-06 20:14:5448
49struct CodecSpecificInfo;
50
Elad Alonfb087812019-05-02 21:25:3451// Each member represents an override of the VPX configuration if the optional
52// value is set.
Elad Alonde3360e2019-03-06 20:14:5453struct Vp8EncoderConfig {
Elad Alonfb087812019-05-02 21:25:3454 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 20:14:5462
Elad Alonfb087812019-05-02 21:25:3463 static constexpr size_t kMaxPeriodicity = 16;
64 static constexpr size_t kMaxLayers = 5;
Elad Alonde3360e2019-03-06 20:14:5465
Elad Alonfb087812019-05-02 21:25:3466 // Number of active temporal layers. Set to 0 if not used.
67 uint32_t ts_number_layers;
68
Artem Titov0e61fdd2021-07-25 19:50:1469 // Arrays of length `ts_number_layers`, indicating (cumulative) target
Elad Alonfb087812019-05-02 21:25:3470 // 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
Artem Titov0e61fdd2021-07-25 19:50:1478 // Array of length `ts_periodicity` indicating the sequence of temporal id's
Elad Alonfb087812019-05-02 21:25:3479 // 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 20:14:5484
85 // Target bitrate, in bps.
Elad Alonfb087812019-05-02 21:25:3486 absl::optional<uint32_t> rc_target_bitrate;
Elad Alonde3360e2019-03-06 20:14:5487
Elad Alonfb087812019-05-02 21:25:3488 // Clamp QP to max. Use 0 to disable clamping.
89 absl::optional<uint32_t> rc_max_quantizer;
Elad Alon544dece2019-04-25 12:24:3690
Elad Alonfb087812019-05-02 21:25:3491 // Error resilience mode.
92 absl::optional<uint32_t> g_error_resilient;
Elad Alon5cf39032019-06-12 09:29:0493
94 // If set to true, all previous configuration overrides should be reset.
95 bool reset_previous_configuration_overrides = false;
Elad Alonde3360e2019-03-06 20:14:5496};
97
98// This interface defines a way of delegating the logic of buffer management.
Elad Aloncde8ab22019-03-20 10:56:2099// Multiple streams may be controlled by a single controller, demuxing between
100// them using stream_index.
Elad Alonde3360e2019-03-06 20:14:54101class Vp8FrameBufferController {
102 public:
103 virtual ~Vp8FrameBufferController() = default;
104
Elad Alonfb087812019-05-02 21:25:34105 // 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
Artem Titov0e61fdd2021-07-25 19:50:14109 // Number of streamed controlled by `this`.
Elad Aloncde8ab22019-03-20 10:56:20110 virtual size_t StreamCount() const = 0;
111
Elad Alonde3360e2019-03-06 20:14:54112 // 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 08:02:46117 // 3. The encoder detected a large overshoot and decided to drop and then
Elad Alonde3360e2019-03-06 20:14:54118 // re-encode the image at a low bitrate. In this case the encoder should
Elad Alon1f28c282019-05-07 19:31:21119 // call OnFrameDropped() once to indicate drop, and then call
Elad Alonde3360e2019-03-06 20:14:54120 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 10:56:20121 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 20:14:54122
Elad Alon979c4426a2019-04-17 10:53:08123 // New target bitrate for a stream (each entry in
Artem Titov0e61fdd2021-07-25 19:50:14124 // `bitrates_bps` is for another temporal layer).
Elad Aloncde8ab22019-03-20 10:56:20125 virtual void OnRatesUpdated(size_t stream_index,
126 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 20:14:54127 int framerate_fps) = 0;
128
Elad Alonfb087812019-05-02 21:25:34129 // 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.
Artem Titovcfea2182021-08-09 23:22:31132 // However, if `Vp8EncoderConfig::reset_previous_configuration_overrides`
Artem Titov0e61fdd2021-07-25 19:50:14133 // is set to `true`, all previous overrides are reset.
Elad Alonfb087812019-05-02 21:25:34134 virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
Elad Alonde3360e2019-03-06 20:14:54135
Elad Alon979c4426a2019-04-17 10:53:08136 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 20:14:54137 // 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 Alon979c4426a2019-04-17 10:53:08142 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
143 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 20:14:54144
Artem Titov0e61fdd2021-07-25 19:50:14145 // Called after the encode step is done. `rtp_timestamp` must match the
Elad Alon162a0392019-04-23 13:33:59146 // parameter use in the NextFrameConfig() call.
Artem Titov0e61fdd2021-07-25 19:50:14147 // `is_keyframe` must be true iff the encoder decided to encode this frame as
Elad Alonde3360e2019-03-06 20:14:54148 // a keyframe.
Artem Titov0e61fdd2021-07-25 19:50:14149 // 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`
Elad Alon979c4426a2019-04-17 10:53:08152 // should be set to 0.
Elad Aloncde8ab22019-03-20 10:56:20153 virtual void OnEncodeDone(size_t stream_index,
154 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 20:14:54155 size_t size_bytes,
156 bool is_keyframe,
157 int qp,
158 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 10:56:20159
Elad Alon6796ec22019-04-15 08:07:50160 // 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 10:56:20163 // Called by the encoder when the packet loss rate changes.
Artem Titov0e61fdd2021-07-25 19:50:14164 // `packet_loss_rate` runs between 0.0 (no loss) and 1.0 (everything lost).
Elad Aloncde8ab22019-03-20 10:56:20165 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 10:28:51169
170 // Called when a loss notification is received.
171 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 10:48:06172 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 10:56:20173};
174
175// Interface for a factory of Vp8FrameBufferController instances.
176class Vp8FrameBufferControllerFactory {
177 public:
178 virtual ~Vp8FrameBufferControllerFactory() = default;
179
Elad Alond9c900f2019-06-17 12:36:27180 // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.)
Elad Alone8df4822019-06-26 09:51:04181 virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0;
Elad Alond9c900f2019-06-17 12:36:27182
Elad Alone8df4822019-06-26 09:51:04183 // Create a Vp8FrameBufferController instance.
Elad Alon45befc52019-07-02 09:20:09184 virtual std::unique_ptr<Vp8FrameBufferController> Create(
185 const VideoCodec& codec,
186 const VideoEncoder::Settings& settings,
Elad Aloned56cf42019-07-02 09:20:23187 FecControllerOverride* fec_controller_override) = 0;
Elad Alonde3360e2019-03-06 20:14:54188};
189
190} // namespace webrtc
191
192#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_