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 "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h"
11 :
12 : #include <assert.h>
13 : #include <stdlib.h>
14 : #include <string.h>
15 :
16 : #include <algorithm>
17 : #include <vector>
18 :
19 : #include "webrtc/base/checks.h"
20 : #include "webrtc/modules/include/module_common_types.h"
21 : #include "webrtc/modules/video_coding/include/video_codec_interface.h"
22 : #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
23 :
24 : #include "vpx/vpx_encoder.h"
25 : #include "vpx/vp8cx.h"
26 :
27 : namespace webrtc {
28 :
29 0 : DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers,
30 0 : uint8_t initial_tl0_pic_idx)
31 : : number_of_temporal_layers_(number_of_temporal_layers),
32 : temporal_ids_length_(0),
33 : temporal_pattern_length_(0),
34 : tl0_pic_idx_(initial_tl0_pic_idx),
35 : pattern_idx_(255),
36 : timestamp_(0),
37 0 : last_base_layer_sync_(false) {
38 0 : RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers);
39 0 : RTC_CHECK_GE(number_of_temporal_layers, 0);
40 0 : memset(temporal_ids_, 0, sizeof(temporal_ids_));
41 0 : memset(temporal_pattern_, 0, sizeof(temporal_pattern_));
42 0 : }
43 :
44 0 : int DefaultTemporalLayers::CurrentLayerId() const {
45 0 : assert(temporal_ids_length_ > 0);
46 0 : int index = pattern_idx_ % temporal_ids_length_;
47 0 : assert(index >= 0);
48 0 : return temporal_ids_[index];
49 : }
50 :
51 0 : std::vector<uint32_t> DefaultTemporalLayers::OnRatesUpdated(
52 : int bitrate_kbps,
53 : int max_bitrate_kbps,
54 : int framerate) {
55 0 : std::vector<uint32_t> bitrates;
56 0 : const int num_layers = std::max(1, number_of_temporal_layers_);
57 0 : for (int i = 0; i < num_layers; ++i) {
58 : float layer_bitrate =
59 0 : bitrate_kbps * kVp8LayerRateAlloction[num_layers - 1][i];
60 0 : bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5));
61 : }
62 0 : new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates);
63 :
64 : // Allocation table is of aggregates, transform to individual rates.
65 0 : uint32_t sum = 0;
66 0 : for (int i = 0; i < num_layers; ++i) {
67 0 : uint32_t layer_bitrate = bitrates[i];
68 0 : RTC_DCHECK_LE(sum, bitrates[i]);
69 0 : bitrates[i] -= sum;
70 0 : sum = layer_bitrate;
71 :
72 0 : if (sum >= static_cast<uint32_t>(bitrate_kbps)) {
73 : // Sum adds up; any subsequent layers will be 0.
74 0 : bitrates.resize(i + 1);
75 0 : break;
76 : }
77 : }
78 :
79 0 : return bitrates;
80 : }
81 :
82 0 : bool DefaultTemporalLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
83 0 : if (!new_bitrates_kbps_)
84 0 : return false;
85 :
86 0 : switch (number_of_temporal_layers_) {
87 : case 0:
88 : FALLTHROUGH();
89 : case 1:
90 0 : temporal_ids_length_ = 1;
91 0 : temporal_ids_[0] = 0;
92 0 : cfg->ts_number_layers = number_of_temporal_layers_;
93 0 : cfg->ts_periodicity = temporal_ids_length_;
94 0 : cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
95 0 : cfg->ts_rate_decimator[0] = 1;
96 0 : memcpy(cfg->ts_layer_id, temporal_ids_,
97 0 : sizeof(unsigned int) * temporal_ids_length_);
98 0 : temporal_pattern_length_ = 1;
99 0 : temporal_pattern_[0] = kTemporalUpdateLastRefAll;
100 0 : break;
101 : case 2:
102 0 : temporal_ids_length_ = 2;
103 0 : temporal_ids_[0] = 0;
104 0 : temporal_ids_[1] = 1;
105 0 : cfg->ts_number_layers = number_of_temporal_layers_;
106 0 : cfg->ts_periodicity = temporal_ids_length_;
107 : // Split stream 60% 40%.
108 : // Bitrate API for VP8 is the agregated bitrate for all lower layers.
109 0 : cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
110 0 : cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
111 0 : cfg->ts_rate_decimator[0] = 2;
112 0 : cfg->ts_rate_decimator[1] = 1;
113 0 : memcpy(cfg->ts_layer_id, temporal_ids_,
114 0 : sizeof(unsigned int) * temporal_ids_length_);
115 0 : temporal_pattern_length_ = 8;
116 0 : temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
117 0 : temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
118 0 : temporal_pattern_[2] = kTemporalUpdateLastRefAltRef;
119 0 : temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef;
120 0 : temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
121 0 : temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef;
122 0 : temporal_pattern_[6] = kTemporalUpdateLastRefAltRef;
123 0 : temporal_pattern_[7] = kTemporalUpdateNone;
124 0 : break;
125 : case 3:
126 0 : temporal_ids_length_ = 4;
127 0 : temporal_ids_[0] = 0;
128 0 : temporal_ids_[1] = 2;
129 0 : temporal_ids_[2] = 1;
130 0 : temporal_ids_[3] = 2;
131 0 : cfg->ts_number_layers = number_of_temporal_layers_;
132 0 : cfg->ts_periodicity = temporal_ids_length_;
133 : // Split stream 40% 20% 40%.
134 : // Bitrate API for VP8 is the agregated bitrate for all lower layers.
135 0 : cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
136 0 : cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
137 0 : cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
138 0 : cfg->ts_rate_decimator[0] = 4;
139 0 : cfg->ts_rate_decimator[1] = 2;
140 0 : cfg->ts_rate_decimator[2] = 1;
141 0 : memcpy(cfg->ts_layer_id, temporal_ids_,
142 0 : sizeof(unsigned int) * temporal_ids_length_);
143 0 : temporal_pattern_length_ = 8;
144 0 : temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
145 0 : temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
146 0 : temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
147 0 : temporal_pattern_[3] = kTemporalUpdateNone;
148 0 : temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
149 0 : temporal_pattern_[5] = kTemporalUpdateNone;
150 0 : temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef;
151 0 : temporal_pattern_[7] = kTemporalUpdateNone;
152 0 : break;
153 : case 4:
154 0 : temporal_ids_length_ = 8;
155 0 : temporal_ids_[0] = 0;
156 0 : temporal_ids_[1] = 3;
157 0 : temporal_ids_[2] = 2;
158 0 : temporal_ids_[3] = 3;
159 0 : temporal_ids_[4] = 1;
160 0 : temporal_ids_[5] = 3;
161 0 : temporal_ids_[6] = 2;
162 0 : temporal_ids_[7] = 3;
163 : // Split stream 25% 15% 20% 40%.
164 : // Bitrate API for VP8 is the agregated bitrate for all lower layers.
165 0 : cfg->ts_number_layers = 4;
166 0 : cfg->ts_periodicity = temporal_ids_length_;
167 0 : cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
168 0 : cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
169 0 : cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
170 0 : cfg->ts_target_bitrate[3] = (*new_bitrates_kbps_)[3];
171 0 : cfg->ts_rate_decimator[0] = 8;
172 0 : cfg->ts_rate_decimator[1] = 4;
173 0 : cfg->ts_rate_decimator[2] = 2;
174 0 : cfg->ts_rate_decimator[3] = 1;
175 0 : memcpy(cfg->ts_layer_id, temporal_ids_,
176 0 : sizeof(unsigned int) * temporal_ids_length_);
177 0 : temporal_pattern_length_ = 16;
178 0 : temporal_pattern_[0] = kTemporalUpdateLast;
179 0 : temporal_pattern_[1] = kTemporalUpdateNone;
180 0 : temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency;
181 0 : temporal_pattern_[3] = kTemporalUpdateNone;
182 0 : temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency;
183 0 : temporal_pattern_[5] = kTemporalUpdateNone;
184 0 : temporal_pattern_[6] = kTemporalUpdateAltref;
185 0 : temporal_pattern_[7] = kTemporalUpdateNone;
186 0 : temporal_pattern_[8] = kTemporalUpdateLast;
187 0 : temporal_pattern_[9] = kTemporalUpdateNone;
188 0 : temporal_pattern_[10] = kTemporalUpdateAltref;
189 0 : temporal_pattern_[11] = kTemporalUpdateNone;
190 0 : temporal_pattern_[12] = kTemporalUpdateGolden;
191 0 : temporal_pattern_[13] = kTemporalUpdateNone;
192 0 : temporal_pattern_[14] = kTemporalUpdateAltref;
193 0 : temporal_pattern_[15] = kTemporalUpdateNone;
194 0 : break;
195 : default:
196 0 : RTC_NOTREACHED();
197 0 : return false;
198 : }
199 :
200 0 : new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
201 :
202 0 : return true;
203 : }
204 :
205 0 : int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) {
206 0 : assert(number_of_temporal_layers_ > 0);
207 0 : assert(kMaxTemporalPattern >= temporal_pattern_length_);
208 0 : assert(0 < temporal_pattern_length_);
209 0 : int flags = 0;
210 0 : int patternIdx = ++pattern_idx_ % temporal_pattern_length_;
211 0 : assert(kMaxTemporalPattern >= patternIdx);
212 0 : switch (temporal_pattern_[patternIdx]) {
213 : case kTemporalUpdateLast:
214 0 : flags |= VP8_EFLAG_NO_UPD_GF;
215 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
216 0 : flags |= VP8_EFLAG_NO_REF_GF;
217 0 : flags |= VP8_EFLAG_NO_REF_ARF;
218 0 : break;
219 : case kTemporalUpdateGoldenWithoutDependency:
220 0 : flags |= VP8_EFLAG_NO_REF_GF;
221 : // Deliberately no break here.
222 : FALLTHROUGH();
223 : case kTemporalUpdateGolden:
224 0 : flags |= VP8_EFLAG_NO_REF_ARF;
225 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
226 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
227 0 : break;
228 : case kTemporalUpdateAltrefWithoutDependency:
229 0 : flags |= VP8_EFLAG_NO_REF_ARF;
230 0 : flags |= VP8_EFLAG_NO_REF_GF;
231 : // Deliberately no break here.
232 : FALLTHROUGH();
233 : case kTemporalUpdateAltref:
234 0 : flags |= VP8_EFLAG_NO_UPD_GF;
235 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
236 0 : break;
237 : case kTemporalUpdateNoneNoRefAltref:
238 0 : flags |= VP8_EFLAG_NO_REF_ARF;
239 : // Deliberately no break here.
240 : FALLTHROUGH();
241 : case kTemporalUpdateNone:
242 0 : flags |= VP8_EFLAG_NO_UPD_GF;
243 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
244 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
245 0 : flags |= VP8_EFLAG_NO_UPD_ENTROPY;
246 0 : break;
247 : case kTemporalUpdateNoneNoRefGoldenRefAltRef:
248 0 : flags |= VP8_EFLAG_NO_REF_GF;
249 0 : flags |= VP8_EFLAG_NO_UPD_GF;
250 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
251 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
252 0 : flags |= VP8_EFLAG_NO_UPD_ENTROPY;
253 0 : break;
254 : case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
255 0 : flags |= VP8_EFLAG_NO_REF_GF;
256 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
257 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
258 0 : break;
259 : case kTemporalUpdateLastRefAltRef:
260 0 : flags |= VP8_EFLAG_NO_UPD_GF;
261 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
262 0 : flags |= VP8_EFLAG_NO_REF_GF;
263 0 : break;
264 : case kTemporalUpdateGoldenRefAltRef:
265 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
266 0 : flags |= VP8_EFLAG_NO_UPD_LAST;
267 0 : break;
268 : case kTemporalUpdateLastAndGoldenRefAltRef:
269 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
270 0 : flags |= VP8_EFLAG_NO_REF_GF;
271 0 : break;
272 : case kTemporalUpdateLastRefAll:
273 0 : flags |= VP8_EFLAG_NO_UPD_ARF;
274 0 : flags |= VP8_EFLAG_NO_UPD_GF;
275 0 : break;
276 : }
277 0 : return flags;
278 : }
279 :
280 0 : void DefaultTemporalLayers::PopulateCodecSpecific(
281 : bool base_layer_sync,
282 : CodecSpecificInfoVP8* vp8_info,
283 : uint32_t timestamp) {
284 0 : assert(number_of_temporal_layers_ > 0);
285 0 : assert(0 < temporal_ids_length_);
286 :
287 0 : if (number_of_temporal_layers_ == 1) {
288 0 : vp8_info->temporalIdx = kNoTemporalIdx;
289 0 : vp8_info->layerSync = false;
290 0 : vp8_info->tl0PicIdx = kNoTl0PicIdx;
291 : } else {
292 0 : if (base_layer_sync) {
293 0 : vp8_info->temporalIdx = 0;
294 0 : vp8_info->layerSync = true;
295 : } else {
296 0 : vp8_info->temporalIdx = CurrentLayerId();
297 : TemporalReferences temporal_reference =
298 0 : temporal_pattern_[pattern_idx_ % temporal_pattern_length_];
299 :
300 0 : if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
301 0 : temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
302 : temporal_reference ==
303 0 : kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
304 0 : temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
305 0 : (temporal_reference == kTemporalUpdateNone &&
306 0 : number_of_temporal_layers_ == 4)) {
307 0 : vp8_info->layerSync = true;
308 : } else {
309 0 : vp8_info->layerSync = false;
310 : }
311 : }
312 0 : if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
313 : // Regardless of pattern the frame after a base layer sync will always
314 : // be a layer sync.
315 0 : vp8_info->layerSync = true;
316 : }
317 0 : if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
318 0 : timestamp_ = timestamp;
319 0 : tl0_pic_idx_++;
320 : }
321 0 : last_base_layer_sync_ = base_layer_sync;
322 0 : vp8_info->tl0PicIdx = tl0_pic_idx_;
323 : }
324 0 : }
325 :
326 0 : TemporalLayers* TemporalLayersFactory::Create(
327 : int simulcast_id,
328 : int temporal_layers,
329 : uint8_t initial_tl0_pic_idx) const {
330 : TemporalLayers* tl =
331 0 : new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
332 0 : if (listener_)
333 0 : listener_->OnTemporalLayersCreated(simulcast_id, tl);
334 0 : return tl;
335 : }
336 :
337 0 : void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) {
338 0 : listener_ = listener;
339 0 : }
340 :
341 : } // namespace webrtc
|