blob: e0d48515afcc1bbb14117d940515a9ee4082f565 [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 Aloncde8ab22019-03-20 11:56:20 +010019#include "api/video_codecs/video_codec.h"
Elad Alon6c371ca2019-04-04 12:28:51 +020020#include "api/video_codecs/video_encoder.h"
Elad Alonde3360e2019-03-06 21:14:54 +010021#include "api/video_codecs/vp8_frame_config.h"
22
23namespace webrtc {
24
25// Some notes on the prerequisites of the TemporalLayers interface.
26// * Vp8FrameBufferController is not thread safe, synchronization is the
27// caller's responsibility.
28// * The encoder is assumed to encode all frames in order, and callbacks to
Elad Alon979c4422019-04-17 12:53:08 +020029// PopulateCodecSpecific() / OnEncodeDone() must happen in the same order.
Elad Alonde3360e2019-03-06 21:14:54 +010030//
31// This means that in the case of pipelining encoders, it is OK to have a chain
32// of calls such as this:
Elad Alon162a0392019-04-23 15:33:59 +020033// - NextFrameConfig(timestampA)
34// - NextFrameConfig(timestampB)
Elad Alonde3360e2019-03-06 21:14:54 +010035// - PopulateCodecSpecific(timestampA, ...)
Elad Alon162a0392019-04-23 15:33:59 +020036// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010037// - OnEncodeDone(timestampA, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020038// - NextFrameConfig(timestampC)
Elad Alonde3360e2019-03-06 21:14:54 +010039// - OnEncodeDone(timestampB, 0, ...)
40// - OnEncodeDone(timestampC, 1234, ...)
Elad Alon162a0392019-04-23 15:33:59 +020041// Note that NextFrameConfig() for a new frame can happen before
Elad Alon979c4422019-04-17 12:53:08 +020042// OnEncodeDone() for a previous one, but calls themselves must be both
Elad Alonde3360e2019-03-06 21:14:54 +010043// synchronized (e.g. run on a task queue) and in order (per type).
Elad Alon979c4422019-04-17 12:53:08 +020044//
45// TODO(eladalon): Revise comment (referring to PopulateCodecSpecific in this
46// context is not very meaningful).
Elad Alonde3360e2019-03-06 21:14:54 +010047
48struct CodecSpecificInfo;
49
Elad Alonfb087812019-05-02 23:25:34 +020050// Each member represents an override of the VPX configuration if the optional
51// value is set.
Elad Alonde3360e2019-03-06 21:14:54 +010052struct Vp8EncoderConfig {
Elad Alonfb087812019-05-02 23:25:34 +020053 struct TemporalLayerConfig {
54 bool operator!=(const TemporalLayerConfig& other) const {
55 return ts_number_layers != other.ts_number_layers ||
56 ts_target_bitrate != other.ts_target_bitrate ||
57 ts_rate_decimator != other.ts_rate_decimator ||
58 ts_periodicity != other.ts_periodicity ||
59 ts_layer_id != other.ts_layer_id;
60 }
Elad Alonde3360e2019-03-06 21:14:54 +010061
Elad Alonfb087812019-05-02 23:25:34 +020062 static constexpr size_t kMaxPeriodicity = 16;
63 static constexpr size_t kMaxLayers = 5;
Elad Alonde3360e2019-03-06 21:14:54 +010064
Elad Alonfb087812019-05-02 23:25:34 +020065 // Number of active temporal layers. Set to 0 if not used.
66 uint32_t ts_number_layers;
67
68 // Arrays of length |ts_number_layers|, indicating (cumulative) target
69 // bitrate and rate decimator (e.g. 4 if every 4th frame is in the given
70 // layer) for each active temporal layer, starting with temporal id 0.
71 std::array<uint32_t, kMaxLayers> ts_target_bitrate;
72 std::array<uint32_t, kMaxLayers> ts_rate_decimator;
73
74 // The periodicity of the temporal pattern. Set to 0 if not used.
75 uint32_t ts_periodicity;
76
77 // Array of length |ts_periodicity| indicating the sequence of temporal id's
78 // to assign to incoming frames.
79 std::array<uint32_t, kMaxPeriodicity> ts_layer_id;
80 };
81
82 absl::optional<TemporalLayerConfig> temporal_layer_config;
Elad Alonde3360e2019-03-06 21:14:54 +010083
84 // Target bitrate, in bps.
Elad Alonfb087812019-05-02 23:25:34 +020085 absl::optional<uint32_t> rc_target_bitrate;
Elad Alonde3360e2019-03-06 21:14:54 +010086
Elad Alonfb087812019-05-02 23:25:34 +020087 // Clamp QP to max. Use 0 to disable clamping.
88 absl::optional<uint32_t> rc_max_quantizer;
Elad Alon544dece2019-04-25 14:24:36 +020089
Elad Alonfb087812019-05-02 23:25:34 +020090 // Error resilience mode.
91 absl::optional<uint32_t> g_error_resilient;
Elad Alon5cf39032019-06-12 11:29:04 +020092
93 // If set to true, all previous configuration overrides should be reset.
94 bool reset_previous_configuration_overrides = false;
Elad Alonde3360e2019-03-06 21:14:54 +010095};
96
97// This interface defines a way of delegating the logic of buffer management.
Elad Aloncde8ab22019-03-20 11:56:20 +010098// Multiple streams may be controlled by a single controller, demuxing between
99// them using stream_index.
Elad Alonde3360e2019-03-06 21:14:54 +0100100class Vp8FrameBufferController {
101 public:
102 virtual ~Vp8FrameBufferController() = default;
103
Elad Alonfb087812019-05-02 23:25:34 +0200104 // Set limits on QP.
105 // The limits are suggestion-only; the controller is allowed to exceed them.
106 virtual void SetQpLimits(size_t stream_index, int min_qp, int max_qp) = 0;
107
Elad Aloncde8ab22019-03-20 11:56:20 +0100108 // Number of streamed controlled by |this|.
109 virtual size_t StreamCount() const = 0;
110
Elad Alonde3360e2019-03-06 21:14:54 +0100111 // If this method returns true, the encoder is free to drop frames for
112 // instance in an effort to uphold encoding bitrate.
113 // If this return false, the encoder must not drop any frames unless:
114 // 1. Requested to do so via Vp8FrameConfig.drop_frame
115 // 2. The frame to be encoded is requested to be a keyframe
Elad Alon6cdbf3f2019-05-08 10:02:46 +0200116 // 3. The encoder detected a large overshoot and decided to drop and then
Elad Alonde3360e2019-03-06 21:14:54 +0100117 // re-encode the image at a low bitrate. In this case the encoder should
Elad Alon1f28c282019-05-07 21:31:21 +0200118 // call OnFrameDropped() once to indicate drop, and then call
Elad Alonde3360e2019-03-06 21:14:54 +0100119 // OnEncodeDone() again when the frame has actually been encoded.
Elad Aloncde8ab22019-03-20 11:56:20 +0100120 virtual bool SupportsEncoderFrameDropping(size_t stream_index) const = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100121
Elad Alon979c4422019-04-17 12:53:08 +0200122 // New target bitrate for a stream (each entry in
123 // |bitrates_bps| is for another temporal layer).
Elad Aloncde8ab22019-03-20 11:56:20 +0100124 virtual void OnRatesUpdated(size_t stream_index,
125 const std::vector<uint32_t>& bitrates_bps,
Elad Alonde3360e2019-03-06 21:14:54 +0100126 int framerate_fps) = 0;
127
Elad Alonfb087812019-05-02 23:25:34 +0200128 // Called by the encoder before encoding a frame. Returns a set of overrides
129 // the controller wishes to enact in the encoder's configuration.
130 // If a value is not overridden, previous overrides are still in effect.
Elad Alon5cf39032019-06-12 11:29:04 +0200131 // However, if |Vp8EncoderConfig::reset_previous_configuration_overrides|
132 // is set to |true|, all previous overrides are reset.
Elad Alonfb087812019-05-02 23:25:34 +0200133 virtual Vp8EncoderConfig UpdateConfiguration(size_t stream_index) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100134
Elad Alon979c4422019-04-17 12:53:08 +0200135 // Returns the recommended VP8 encode flags needed.
Elad Alonde3360e2019-03-06 21:14:54 +0100136 // The timestamp may be used as both a time and a unique identifier, and so
137 // the caller must make sure no two frames use the same timestamp.
138 // The timestamp uses a 90kHz RTP clock.
139 // After calling this method, first call the actual encoder with the provided
140 // frame configuration, and then OnEncodeDone() below.
Elad Alon979c4422019-04-17 12:53:08 +0200141 virtual Vp8FrameConfig NextFrameConfig(size_t stream_index,
142 uint32_t rtp_timestamp) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100143
144 // Called after the encode step is done. |rtp_timestamp| must match the
Elad Alon162a0392019-04-23 15:33:59 +0200145 // parameter use in the NextFrameConfig() call.
Elad Alonde3360e2019-03-06 21:14:54 +0100146 // |is_keyframe| must be true iff the encoder decided to encode this frame as
147 // a keyframe.
Elad Alon979c4422019-04-17 12:53:08 +0200148 // If |info| is not null, the encoder may update |info| with codec specific
149 // data such as temporal id. |qp| should indicate the frame-level QP this
150 // frame was encoded at. If the encoder does not support extracting this, |qp|
151 // should be set to 0.
Elad Aloncde8ab22019-03-20 11:56:20 +0100152 virtual void OnEncodeDone(size_t stream_index,
153 uint32_t rtp_timestamp,
Elad Alonde3360e2019-03-06 21:14:54 +0100154 size_t size_bytes,
155 bool is_keyframe,
156 int qp,
157 CodecSpecificInfo* info) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100158
Elad Alon6796ec22019-04-15 10:07:50 +0200159 // Called when a frame is dropped by the encoder.
160 virtual void OnFrameDropped(size_t stream_index, uint32_t rtp_timestamp) = 0;
161
Elad Aloncde8ab22019-03-20 11:56:20 +0100162 // Called by the encoder when the packet loss rate changes.
163 // |packet_loss_rate| runs between 0.0 (no loss) and 1.0 (everything lost).
164 virtual void OnPacketLossRateUpdate(float packet_loss_rate) = 0;
165
166 // Called by the encoder when the round trip time changes.
167 virtual void OnRttUpdate(int64_t rtt_ms) = 0;
Elad Alon6c371ca2019-04-04 12:28:51 +0200168
169 // Called when a loss notification is received.
170 virtual void OnLossNotification(
Elad Alon123ee9b2019-04-17 12:48:06 +0200171 const VideoEncoder::LossNotification& loss_notification) = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100172};
173
174// Interface for a factory of Vp8FrameBufferController instances.
175class Vp8FrameBufferControllerFactory {
176 public:
177 virtual ~Vp8FrameBufferControllerFactory() = default;
178
Elad Alond9c900f2019-06-17 14:36:27 +0200179 // Clones oneself. (Avoids Vp8FrameBufferControllerFactoryFactory.)
Elad Alone8df4822019-06-26 11:51:04 +0200180 virtual std::unique_ptr<Vp8FrameBufferControllerFactory> Clone() const = 0;
Elad Alond9c900f2019-06-17 14:36:27 +0200181
Elad Alone8df4822019-06-26 11:51:04 +0200182 // Create a Vp8FrameBufferController instance.
Elad Alona2795842019-06-07 23:10:00 +0200183 virtual std::unique_ptr<Vp8FrameBufferController> Create(
184 const VideoCodec& codec,
Elad Alone8df4822019-06-26 11:51:04 +0200185 const VideoEncoder::Settings& settings) = 0;
Elad Alonde3360e2019-03-06 21:14:54 +0100186};
187
188} // namespace webrtc
189
190#endif // API_VIDEO_CODECS_VP8_FRAME_BUFFER_CONTROLLER_H_