Line data Source code
1 : /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
2 : *
3 : * Use of this source code is governed by a BSD-style license
4 : * that can be found in the LICENSE file in the root of the source
5 : * tree. An additional intellectual property rights grant can be found
6 : * in the file PATENTS. All contributing project authors may
7 : * be found in the AUTHORS file in the root of the source tree.
8 : */
9 :
10 : #include <stdlib.h>
11 : #include <algorithm>
12 :
13 : #include "vpx/vpx_encoder.h"
14 : #include "vpx/vp8cx.h"
15 : #include "webrtc/base/checks.h"
16 : #include "webrtc/base/optional.h"
17 : #include "webrtc/modules/video_coding/include/video_codec_interface.h"
18 : #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
19 : #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
20 :
21 : // This file implements logic to adapt the number of temporal layers based on
22 : // input frame rate in order to avoid having the base layer being relaying at
23 : // a below acceptable framerate.
24 : namespace webrtc {
25 : namespace {
26 : enum {
27 : kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
28 : VP8_EFLAG_NO_REF_GF |
29 : VP8_EFLAG_NO_REF_ARF,
30 :
31 : kTemporalUpdateGolden =
32 : VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
33 :
34 : kTemporalUpdateGoldenWithoutDependency =
35 : kTemporalUpdateGolden | VP8_EFLAG_NO_REF_GF,
36 :
37 : kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST,
38 :
39 : kTemporalUpdateAltrefWithoutDependency =
40 : kTemporalUpdateAltref | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF,
41 :
42 : kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
43 : VP8_EFLAG_NO_UPD_LAST |
44 : VP8_EFLAG_NO_UPD_ENTROPY,
45 :
46 : kTemporalUpdateNoneNoRefAltref = kTemporalUpdateNone | VP8_EFLAG_NO_REF_ARF,
47 :
48 : kTemporalUpdateNoneNoRefGoldenRefAltRef =
49 : VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
50 : VP8_EFLAG_NO_UPD_LAST |
51 : VP8_EFLAG_NO_UPD_ENTROPY,
52 :
53 : kTemporalUpdateGoldenWithoutDependencyRefAltRef =
54 : VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
55 :
56 : kTemporalUpdateLastRefAltRef =
57 : VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF,
58 :
59 : kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
60 :
61 : kTemporalUpdateLastAndGoldenRefAltRef =
62 : VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF,
63 :
64 : kTemporalUpdateLastRefAll = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF,
65 : };
66 :
67 0 : int CalculateNumberOfTemporalLayers(int current_temporal_layers,
68 : int input_fps) {
69 0 : if (input_fps >= 24) {
70 0 : return 3;
71 : }
72 0 : if (input_fps >= 20 && current_temporal_layers >= 3) {
73 : // Keep doing 3 temporal layers until we go below 20fps.
74 0 : return 3;
75 : }
76 0 : if (input_fps >= 10) {
77 0 : return 2;
78 : }
79 0 : if (input_fps > 8 && current_temporal_layers >= 2) {
80 : // keep doing 2 temporal layers until we go below 8fps
81 0 : return 2;
82 : }
83 0 : return 1;
84 : }
85 :
86 : class RealTimeTemporalLayers : public TemporalLayers {
87 : public:
88 0 : RealTimeTemporalLayers(int max_num_temporal_layers,
89 : uint8_t initial_tl0_pic_idx)
90 0 : : temporal_layers_(1),
91 : max_temporal_layers_(max_num_temporal_layers),
92 : tl0_pic_idx_(initial_tl0_pic_idx),
93 : frame_counter_(static_cast<unsigned int>(-1)),
94 : timestamp_(0),
95 : last_base_layer_sync_(0),
96 : layer_ids_length_(0),
97 : layer_ids_(nullptr),
98 : encode_flags_length_(0),
99 0 : encode_flags_(nullptr) {
100 0 : RTC_CHECK_GE(max_temporal_layers_, 1);
101 0 : RTC_CHECK_LE(max_temporal_layers_, 3);
102 0 : }
103 :
104 0 : virtual ~RealTimeTemporalLayers() {}
105 :
106 0 : std::vector<uint32_t> OnRatesUpdated(int bitrate_kbps,
107 : int max_bitrate_kbps,
108 : int framerate) override {
109 0 : temporal_layers_ =
110 0 : CalculateNumberOfTemporalLayers(temporal_layers_, framerate);
111 0 : temporal_layers_ = std::min(temporal_layers_, max_temporal_layers_);
112 0 : RTC_CHECK_GE(temporal_layers_, 1);
113 0 : RTC_CHECK_LE(temporal_layers_, 3);
114 :
115 0 : switch (temporal_layers_) {
116 : case 1: {
117 : static const unsigned int layer_ids[] = {0u};
118 0 : layer_ids_ = layer_ids;
119 0 : layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
120 :
121 : static const int encode_flags[] = {kTemporalUpdateLastRefAll};
122 0 : encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
123 0 : encode_flags_ = encode_flags;
124 0 : } break;
125 :
126 : case 2: {
127 : static const unsigned int layer_ids[] = {0u, 1u};
128 0 : layer_ids_ = layer_ids;
129 0 : layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
130 :
131 : static const int encode_flags[] = {
132 : kTemporalUpdateLastAndGoldenRefAltRef,
133 : kTemporalUpdateGoldenWithoutDependencyRefAltRef,
134 : kTemporalUpdateLastRefAltRef,
135 : kTemporalUpdateGoldenRefAltRef,
136 : kTemporalUpdateLastRefAltRef,
137 : kTemporalUpdateGoldenRefAltRef,
138 : kTemporalUpdateLastRefAltRef,
139 : kTemporalUpdateNone};
140 0 : encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
141 0 : encode_flags_ = encode_flags;
142 0 : } break;
143 :
144 : case 3: {
145 : static const unsigned int layer_ids[] = {0u, 2u, 1u, 2u};
146 0 : layer_ids_ = layer_ids;
147 0 : layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
148 :
149 : static const int encode_flags[] = {
150 : kTemporalUpdateLastAndGoldenRefAltRef,
151 : kTemporalUpdateNoneNoRefGoldenRefAltRef,
152 : kTemporalUpdateGoldenWithoutDependencyRefAltRef,
153 : kTemporalUpdateNone,
154 : kTemporalUpdateLastRefAltRef,
155 : kTemporalUpdateNone,
156 : kTemporalUpdateGoldenRefAltRef,
157 : kTemporalUpdateNone};
158 0 : encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
159 0 : encode_flags_ = encode_flags;
160 0 : } break;
161 :
162 : default:
163 0 : RTC_NOTREACHED();
164 0 : return std::vector<uint32_t>();
165 : }
166 :
167 0 : std::vector<uint32_t> bitrates;
168 0 : const int num_layers = std::max(1, temporal_layers_);
169 0 : for (int i = 0; i < num_layers; ++i) {
170 : float layer_bitrate =
171 0 : bitrate_kbps * kVp8LayerRateAlloction[num_layers - 1][i];
172 0 : bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5));
173 : }
174 0 : new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates);
175 :
176 : // Allocation table is of aggregates, transform to individual rates.
177 0 : uint32_t sum = 0;
178 0 : for (int i = 0; i < num_layers; ++i) {
179 0 : uint32_t layer_bitrate = bitrates[i];
180 0 : RTC_DCHECK_LE(sum, bitrates[i]);
181 0 : bitrates[i] -= sum;
182 0 : sum = layer_bitrate;
183 :
184 0 : if (sum >= static_cast<uint32_t>(bitrate_kbps)) {
185 : // Sum adds up; any subsequent layers will be 0.
186 0 : bitrates.resize(i + 1);
187 0 : break;
188 : }
189 : }
190 :
191 0 : return bitrates;
192 : }
193 :
194 0 : bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override {
195 0 : if (!new_bitrates_kbps_)
196 0 : return false;
197 :
198 0 : cfg->ts_number_layers = temporal_layers_;
199 0 : for (int tl = 0; tl < temporal_layers_; ++tl) {
200 0 : cfg->ts_target_bitrate[tl] = (*new_bitrates_kbps_)[tl];
201 : }
202 0 : new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
203 :
204 0 : cfg->ts_periodicity = layer_ids_length_;
205 0 : int decimator = 1;
206 0 : for (int i = temporal_layers_ - 1; i >= 0; --i, decimator *= 2) {
207 0 : cfg->ts_rate_decimator[i] = decimator;
208 : }
209 :
210 0 : memcpy(cfg->ts_layer_id, layer_ids_,
211 0 : sizeof(unsigned int) * layer_ids_length_);
212 :
213 0 : return true;
214 : }
215 :
216 0 : int EncodeFlags(uint32_t timestamp) override {
217 0 : frame_counter_++;
218 0 : return CurrentEncodeFlags();
219 : }
220 :
221 0 : int CurrentEncodeFlags() const {
222 0 : assert(encode_flags_length_ > 0 && encode_flags_ != NULL);
223 0 : int index = frame_counter_ % encode_flags_length_;
224 0 : assert(index >= 0 && index < encode_flags_length_);
225 0 : return encode_flags_[index];
226 : }
227 :
228 0 : int CurrentLayerId() const override {
229 0 : assert(layer_ids_length_ > 0 && layer_ids_ != NULL);
230 0 : int index = frame_counter_ % layer_ids_length_;
231 0 : assert(index >= 0 && index < layer_ids_length_);
232 0 : return layer_ids_[index];
233 : }
234 :
235 0 : void PopulateCodecSpecific(bool base_layer_sync,
236 : CodecSpecificInfoVP8* vp8_info,
237 : uint32_t timestamp) override {
238 0 : assert(temporal_layers_ > 0);
239 :
240 0 : if (temporal_layers_ == 1) {
241 0 : vp8_info->temporalIdx = kNoTemporalIdx;
242 0 : vp8_info->layerSync = false;
243 0 : vp8_info->tl0PicIdx = kNoTl0PicIdx;
244 : } else {
245 0 : if (base_layer_sync) {
246 0 : vp8_info->temporalIdx = 0;
247 0 : vp8_info->layerSync = true;
248 : } else {
249 0 : vp8_info->temporalIdx = CurrentLayerId();
250 0 : int temporal_reference = CurrentEncodeFlags();
251 :
252 0 : if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
253 0 : temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
254 : temporal_reference ==
255 0 : kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
256 0 : temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
257 0 : (temporal_reference == kTemporalUpdateNone &&
258 0 : temporal_layers_ == 4)) {
259 0 : vp8_info->layerSync = true;
260 : } else {
261 0 : vp8_info->layerSync = false;
262 : }
263 : }
264 0 : if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
265 : // Regardless of pattern the frame after a base layer sync will always
266 : // be a layer sync.
267 0 : vp8_info->layerSync = true;
268 : }
269 0 : if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
270 0 : timestamp_ = timestamp;
271 0 : tl0_pic_idx_++;
272 : }
273 0 : last_base_layer_sync_ = base_layer_sync;
274 0 : vp8_info->tl0PicIdx = tl0_pic_idx_;
275 : }
276 0 : }
277 :
278 0 : void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {}
279 :
280 : private:
281 : int temporal_layers_;
282 : int max_temporal_layers_;
283 :
284 : int tl0_pic_idx_;
285 : unsigned int frame_counter_;
286 : uint32_t timestamp_;
287 : bool last_base_layer_sync_;
288 :
289 : // Pattern of temporal layer ids.
290 : int layer_ids_length_;
291 : const unsigned int* layer_ids_;
292 :
293 : // Pattern of encode flags.
294 : int encode_flags_length_;
295 : const int* encode_flags_;
296 :
297 : rtc::Optional<std::vector<uint32_t>> new_bitrates_kbps_;
298 : };
299 : } // namespace
300 :
301 0 : TemporalLayers* RealTimeTemporalLayersFactory::Create(
302 : int simulcast_id,
303 : int max_temporal_layers,
304 : uint8_t initial_tl0_pic_idx) const {
305 : TemporalLayers* tl =
306 0 : new RealTimeTemporalLayers(max_temporal_layers, initial_tl0_pic_idx);
307 0 : if (listener_)
308 0 : listener_->OnTemporalLayersCreated(simulcast_id, tl);
309 0 : return tl;
310 : }
311 : } // namespace webrtc
|