blob: ecc7e3df5efddd2294a2b86ae4b3dabdb03e11d7 [file] [log] [blame]
Erik Språng8abd56c2018-10-01 18:47:03 +02001/*
2 * Copyright (c) 2018 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
Erik Språng4529fbc2018-10-12 10:30:31 +020011#ifndef API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_
12#define API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_
Erik Språng8abd56c2018-10-01 18:47:03 +020013
14#include <memory>
15#include <vector>
16
Elad Alonf5b216a2019-01-28 14:25:17 +010017#include "rtc_base/checks.h"
18
Erik Språng8abd56c2018-10-01 18:47:03 +020019namespace webrtc {
20
21// Some notes on the prerequisites of the TemporalLayers interface.
Erik Språng4529fbc2018-10-12 10:30:31 +020022// * Vp8TemporalLayers is not thread safe, synchronization is the caller's
23// responsibility.
Erik Språng8abd56c2018-10-01 18:47:03 +020024// * The encoder is assumed to encode all frames in order, and callbacks to
25// PopulateCodecSpecific() / FrameEncoded() must happen in the same order.
26//
27// This means that in the case of pipelining encoders, it is OK to have a chain
28// of calls such as this:
29// - UpdateLayerConfig(timestampA)
30// - UpdateLayerConfig(timestampB)
31// - PopulateCodecSpecific(timestampA, ...)
32// - UpdateLayerConfig(timestampC)
Erik Språng59021ba2018-10-03 11:05:16 +020033// - OnEncodeDone(timestampA, 1234, ...)
34// - UpdateLayerConfig(timestampC)
35// - OnEncodeDone(timestampB, 0, ...)
36// - OnEncodeDone(timestampC, 1234, ...)
Erik Språng8abd56c2018-10-01 18:47:03 +020037// Note that UpdateLayerConfig() for a new frame can happen before
38// FrameEncoded() for a previous one, but calls themselves must be both
39// synchronized (e.g. run on a task queue) and in order (per type).
40
Erik Språng4529fbc2018-10-12 10:30:31 +020041// Two different flavors of temporal layers are currently available:
42// kFixedPattern uses a fixed repeating pattern of 1-4 layers.
43// kBitrateDynamic can allocate frames dynamically to 1 or 2 layers, based on
44// the bitrate produced.
45enum class Vp8TemporalLayersType { kFixedPattern, kBitrateDynamic };
Erik Språng8abd56c2018-10-01 18:47:03 +020046
47struct CodecSpecificInfoVP8;
Erik Språng8abd56c2018-10-01 18:47:03 +020048
49struct Vp8EncoderConfig {
50 static constexpr size_t kMaxPeriodicity = 16;
51 static constexpr size_t kMaxLayers = 5;
52
53 // Number of active temporal layers. Set to 0 if not used.
54 uint32_t ts_number_layers;
55 // Arrays of length |ts_number_layers|, indicating (cumulative) target bitrate
56 // and rate decimator (e.g. 4 if every 4th frame is in the given layer) for
57 // each active temporal layer, starting with temporal id 0.
58 uint32_t ts_target_bitrate[kMaxLayers];
59 uint32_t ts_rate_decimator[kMaxLayers];
60
61 // The periodicity of the temporal pattern. Set to 0 if not used.
62 uint32_t ts_periodicity;
63 // Array of length |ts_periodicity| indicating the sequence of temporal id's
64 // to assign to incoming frames.
65 uint32_t ts_layer_id[kMaxPeriodicity];
66
67 // Target bitrate, in bps.
68 uint32_t rc_target_bitrate;
69
70 // Clamp QP to min/max. Use 0 to disable clamping.
71 uint32_t rc_min_quantizer;
72 uint32_t rc_max_quantizer;
73};
74
Erik Språng4529fbc2018-10-12 10:30:31 +020075// Defined bit-maskable reference to the three buffers available in VP8.
76enum class Vp8BufferReference : uint8_t {
77 kNone = 0,
78 kLast = 1,
79 kGolden = 2,
80 kAltref = 4
81};
82
Erik Språng8abd56c2018-10-01 18:47:03 +020083// This interface defines a way of getting the encoder settings needed to
Erik Språng4529fbc2018-10-12 10:30:31 +020084// realize a temporal layer structure.
85class Vp8TemporalLayers {
Erik Språng8abd56c2018-10-01 18:47:03 +020086 public:
87 enum BufferFlags : int {
88 kNone = 0,
89 kReference = 1,
90 kUpdate = 2,
91 kReferenceAndUpdate = kReference | kUpdate,
92 };
93 enum FreezeEntropy { kFreezeEntropy };
94
95 struct FrameConfig {
96 FrameConfig();
97
98 FrameConfig(BufferFlags last, BufferFlags golden, BufferFlags arf);
99 FrameConfig(BufferFlags last,
100 BufferFlags golden,
101 BufferFlags arf,
102 FreezeEntropy);
103
Elad Alonf5b216a2019-01-28 14:25:17 +0100104 enum class Buffer : int { kLast = 0, kGolden = 1, kArf = 2, kCount };
105
106 bool References(Buffer buffer) const {
107 switch (buffer) {
108 case Buffer::kLast:
109 return (last_buffer_flags & kReference) != 0;
110 case Buffer::kGolden:
111 return (golden_buffer_flags & kReference) != 0;
112 case Buffer::kArf:
113 return (arf_buffer_flags & kReference) != 0;
114 case Buffer::kCount:
115 break;
116 }
117 RTC_NOTREACHED();
118 return false;
119 }
120
121 bool Updates(Buffer buffer) const {
122 switch (buffer) {
123 case Buffer::kLast:
124 return (last_buffer_flags & kUpdate) != 0;
125 case Buffer::kGolden:
126 return (golden_buffer_flags & kUpdate) != 0;
127 case Buffer::kArf:
128 return (arf_buffer_flags & kUpdate) != 0;
129 case Buffer::kCount:
130 break;
131 }
132 RTC_NOTREACHED();
133 return false;
134 }
135
Erik Språng8abd56c2018-10-01 18:47:03 +0200136 bool drop_frame;
137 BufferFlags last_buffer_flags;
138 BufferFlags golden_buffer_flags;
139 BufferFlags arf_buffer_flags;
140
141 // The encoder layer ID is used to utilize the correct bitrate allocator
142 // inside the encoder. It does not control references nor determine which
143 // "actual" temporal layer this is. The packetizer temporal index determines
144 // which layer the encoded frame should be packetized into.
145 // Normally these are the same, but current temporal-layer strategies for
146 // screenshare use one bitrate allocator for all layers, but attempt to
147 // packetize / utilize references to split a stream into multiple layers,
148 // with different quantizer settings, to hit target bitrate.
149 // TODO(pbos): Screenshare layers are being reconsidered at the time of
150 // writing, we might be able to remove this distinction, and have a temporal
151 // layer imply both (the normal case).
152 int encoder_layer_id;
153 int packetizer_temporal_idx;
154
155 bool layer_sync;
156
157 bool freeze_entropy;
158
159 // Indicates in which order the encoder should search the reference buffers
160 // when doing motion prediction. Set to kNone to use unspecified order. Any
161 // buffer indicated here must not have the corresponding no_ref bit set.
162 // If all three buffers can be reference, the one not listed here should be
163 // searched last.
164 Vp8BufferReference first_reference;
165 Vp8BufferReference second_reference;
166
Erik Språng8abd56c2018-10-01 18:47:03 +0200167 private:
168 FrameConfig(BufferFlags last,
169 BufferFlags golden,
170 BufferFlags arf,
171 bool freeze_entropy);
172 };
173
Erik Språng4529fbc2018-10-12 10:30:31 +0200174 virtual ~Vp8TemporalLayers() = default;
Erik Språng8abd56c2018-10-01 18:47:03 +0200175
Erik Språng59021ba2018-10-03 11:05:16 +0200176 // If this method returns true, the encoder is free to drop frames for
177 // instance in an effort to uphold encoding bitrate.
178 // If this return false, the encoder must not drop any frames unless:
179 // 1. Requested to do so via FrameConfig.drop_frame
180 // 2. The frame to be encoded is requested to be a keyframe
181 // 3. The encoded detected a large overshoot and decided to drop and then
182 // re-encode the image at a low bitrate. In this case the encoder should
183 // call OnEncodeDone() once with size = 0 to indicate drop, and then call
184 // OnEncodeDone() again when the frame has actually been encoded.
Erik Språng8abd56c2018-10-01 18:47:03 +0200185 virtual bool SupportsEncoderFrameDropping() const = 0;
186
187 // New target bitrate, per temporal layer.
188 virtual void OnRatesUpdated(const std::vector<uint32_t>& bitrates_bps,
189 int framerate_fps) = 0;
190
Erik Språng59021ba2018-10-03 11:05:16 +0200191 // Called by the encoder before encoding a frame. |cfg| contains the current
192 // configuration. If the TemporalLayers instance wishes any part of that
193 // to be changed before the encode step, |cfg| should be changed and then
194 // return true. If false is returned, the encoder will proceed without
195 // updating the configuration.
Erik Språng8abd56c2018-10-01 18:47:03 +0200196 virtual bool UpdateConfiguration(Vp8EncoderConfig* cfg) = 0;
197
198 // Returns the recommended VP8 encode flags needed, and moves the temporal
199 // pattern to the next frame.
200 // The timestamp may be used as both a time and a unique identifier, and so
201 // the caller must make sure no two frames use the same timestamp.
202 // The timestamp uses a 90kHz RTP clock.
Erik Språng59021ba2018-10-03 11:05:16 +0200203 // After calling this method, first call the actual encoder with the provided
204 // frame configuration, and then OnEncodeDone() below.
Erik Språng8abd56c2018-10-01 18:47:03 +0200205 virtual FrameConfig UpdateLayerConfig(uint32_t rtp_timestamp) = 0;
206
Erik Språng59021ba2018-10-03 11:05:16 +0200207 // Called after the encode step is done. |rtp_timestamp| must match the
208 // parameter use in the UpdateLayerConfig() call.
209 // |is_keyframe| must be true iff the encoder decided to encode this frame as
210 // a keyframe.
211 // If the encoder decided to drop this frame, |size_bytes| must be set to 0,
212 // otherwise it should indicate the size in bytes of the encoded frame.
213 // If |size_bytes| > 0, and |vp8_info| is not null, the TemporalLayers
214 // instance my update |vp8_info| with codec specific data such as temporal id.
215 // Some fields of this struct may have already been populated by the encoder,
216 // check before overwriting.
217 // If |size_bytes| > 0, |qp| should indicate the frame-level QP this frame was
218 // encoded at. If the encoder does not support extracting this, |qp| should be
219 // set to 0.
220 virtual void OnEncodeDone(uint32_t rtp_timestamp,
Erik Språng8abd56c2018-10-01 18:47:03 +0200221 size_t size_bytes,
Erik Språng59021ba2018-10-03 11:05:16 +0200222 bool is_keyframe,
223 int qp,
224 CodecSpecificInfoVP8* vp8_info) = 0;
Erik Språng8abd56c2018-10-01 18:47:03 +0200225};
226
227} // namespace webrtc
228
Erik Språng4529fbc2018-10-12 10:30:31 +0200229#endif // API_VIDEO_CODECS_VP8_TEMPORAL_LAYERS_H_