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 "webrtc/modules/include/module_common_types.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
20 #include "vpx/vpx_encoder.h"
21 #include "vpx/vp8cx.h"
22
23 namespace webrtc {
24
DefaultTemporalLayers(int numberOfTemporalLayers,uint8_t initial_tl0_pic_idx)25 DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers,
26 uint8_t initial_tl0_pic_idx)
27 : number_of_temporal_layers_(numberOfTemporalLayers),
28 temporal_ids_length_(0),
29 temporal_pattern_length_(0),
30 tl0_pic_idx_(initial_tl0_pic_idx),
31 pattern_idx_(255),
32 timestamp_(0),
33 last_base_layer_sync_(false) {
34 assert(kMaxTemporalStreams >= numberOfTemporalLayers);
35 memset(temporal_ids_, 0, sizeof(temporal_ids_));
36 memset(temporal_pattern_, 0, sizeof(temporal_pattern_));
37 }
38
CurrentLayerId() const39 int DefaultTemporalLayers::CurrentLayerId() const {
40 assert(temporal_ids_length_ > 0);
41 int index = pattern_idx_ % temporal_ids_length_;
42 assert(index >= 0);
43 return temporal_ids_[index];
44 }
45
ConfigureBitrates(int bitrateKbit,int max_bitrate_kbit,int framerate,vpx_codec_enc_cfg_t * cfg)46 bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
47 int max_bitrate_kbit,
48 int framerate,
49 vpx_codec_enc_cfg_t* cfg) {
50 switch (number_of_temporal_layers_) {
51 case 0:
52 case 1:
53 temporal_ids_length_ = 1;
54 temporal_ids_[0] = 0;
55 cfg->ts_number_layers = number_of_temporal_layers_;
56 cfg->ts_periodicity = temporal_ids_length_;
57 cfg->ts_target_bitrate[0] = bitrateKbit;
58 cfg->ts_rate_decimator[0] = 1;
59 memcpy(cfg->ts_layer_id, temporal_ids_,
60 sizeof(unsigned int) * temporal_ids_length_);
61 temporal_pattern_length_ = 1;
62 temporal_pattern_[0] = kTemporalUpdateLastRefAll;
63 break;
64 case 2:
65 temporal_ids_length_ = 2;
66 temporal_ids_[0] = 0;
67 temporal_ids_[1] = 1;
68 cfg->ts_number_layers = number_of_temporal_layers_;
69 cfg->ts_periodicity = temporal_ids_length_;
70 // Split stream 60% 40%.
71 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
72 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[1][0];
73 cfg->ts_target_bitrate[1] = bitrateKbit;
74 cfg->ts_rate_decimator[0] = 2;
75 cfg->ts_rate_decimator[1] = 1;
76 memcpy(cfg->ts_layer_id, temporal_ids_,
77 sizeof(unsigned int) * temporal_ids_length_);
78 temporal_pattern_length_ = 8;
79 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
80 temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
81 temporal_pattern_[2] = kTemporalUpdateLastRefAltRef;
82 temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef;
83 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
84 temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef;
85 temporal_pattern_[6] = kTemporalUpdateLastRefAltRef;
86 temporal_pattern_[7] = kTemporalUpdateNone;
87 break;
88 case 3:
89 temporal_ids_length_ = 4;
90 temporal_ids_[0] = 0;
91 temporal_ids_[1] = 2;
92 temporal_ids_[2] = 1;
93 temporal_ids_[3] = 2;
94 cfg->ts_number_layers = number_of_temporal_layers_;
95 cfg->ts_periodicity = temporal_ids_length_;
96 // Split stream 40% 20% 40%.
97 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
98 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[2][0];
99 cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[2][1];
100 cfg->ts_target_bitrate[2] = bitrateKbit;
101 cfg->ts_rate_decimator[0] = 4;
102 cfg->ts_rate_decimator[1] = 2;
103 cfg->ts_rate_decimator[2] = 1;
104 memcpy(cfg->ts_layer_id, temporal_ids_,
105 sizeof(unsigned int) * temporal_ids_length_);
106 temporal_pattern_length_ = 8;
107 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
108 temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
109 temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
110 temporal_pattern_[3] = kTemporalUpdateNone;
111 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
112 temporal_pattern_[5] = kTemporalUpdateNone;
113 temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef;
114 temporal_pattern_[7] = kTemporalUpdateNone;
115 break;
116 case 4:
117 temporal_ids_length_ = 8;
118 temporal_ids_[0] = 0;
119 temporal_ids_[1] = 3;
120 temporal_ids_[2] = 2;
121 temporal_ids_[3] = 3;
122 temporal_ids_[4] = 1;
123 temporal_ids_[5] = 3;
124 temporal_ids_[6] = 2;
125 temporal_ids_[7] = 3;
126 // Split stream 25% 15% 20% 40%.
127 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
128 cfg->ts_number_layers = 4;
129 cfg->ts_periodicity = temporal_ids_length_;
130 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[3][0];
131 cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[3][1];
132 cfg->ts_target_bitrate[2] = bitrateKbit * kVp8LayerRateAlloction[3][2];
133 cfg->ts_target_bitrate[3] = bitrateKbit;
134 cfg->ts_rate_decimator[0] = 8;
135 cfg->ts_rate_decimator[1] = 4;
136 cfg->ts_rate_decimator[2] = 2;
137 cfg->ts_rate_decimator[3] = 1;
138 memcpy(cfg->ts_layer_id, temporal_ids_,
139 sizeof(unsigned int) * temporal_ids_length_);
140 temporal_pattern_length_ = 16;
141 temporal_pattern_[0] = kTemporalUpdateLast;
142 temporal_pattern_[1] = kTemporalUpdateNone;
143 temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency;
144 temporal_pattern_[3] = kTemporalUpdateNone;
145 temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency;
146 temporal_pattern_[5] = kTemporalUpdateNone;
147 temporal_pattern_[6] = kTemporalUpdateAltref;
148 temporal_pattern_[7] = kTemporalUpdateNone;
149 temporal_pattern_[8] = kTemporalUpdateLast;
150 temporal_pattern_[9] = kTemporalUpdateNone;
151 temporal_pattern_[10] = kTemporalUpdateAltref;
152 temporal_pattern_[11] = kTemporalUpdateNone;
153 temporal_pattern_[12] = kTemporalUpdateGolden;
154 temporal_pattern_[13] = kTemporalUpdateNone;
155 temporal_pattern_[14] = kTemporalUpdateAltref;
156 temporal_pattern_[15] = kTemporalUpdateNone;
157 break;
158 default:
159 assert(false);
160 return false;
161 }
162 return true;
163 }
164
EncodeFlags(uint32_t timestamp)165 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) {
166 assert(number_of_temporal_layers_ > 0);
167 assert(kMaxTemporalPattern >= temporal_pattern_length_);
168 assert(0 < temporal_pattern_length_);
169 int flags = 0;
170 int patternIdx = ++pattern_idx_ % temporal_pattern_length_;
171 assert(kMaxTemporalPattern >= patternIdx);
172 switch (temporal_pattern_[patternIdx]) {
173 case kTemporalUpdateLast:
174 flags |= VP8_EFLAG_NO_UPD_GF;
175 flags |= VP8_EFLAG_NO_UPD_ARF;
176 flags |= VP8_EFLAG_NO_REF_GF;
177 flags |= VP8_EFLAG_NO_REF_ARF;
178 break;
179 case kTemporalUpdateGoldenWithoutDependency:
180 flags |= VP8_EFLAG_NO_REF_GF;
181 // Deliberately no break here.
182 FALLTHROUGH();
183 case kTemporalUpdateGolden:
184 flags |= VP8_EFLAG_NO_REF_ARF;
185 flags |= VP8_EFLAG_NO_UPD_ARF;
186 flags |= VP8_EFLAG_NO_UPD_LAST;
187 break;
188 case kTemporalUpdateAltrefWithoutDependency:
189 flags |= VP8_EFLAG_NO_REF_ARF;
190 flags |= VP8_EFLAG_NO_REF_GF;
191 // Deliberately no break here.
192 FALLTHROUGH();
193 case kTemporalUpdateAltref:
194 flags |= VP8_EFLAG_NO_UPD_GF;
195 flags |= VP8_EFLAG_NO_UPD_LAST;
196 break;
197 case kTemporalUpdateNoneNoRefAltref:
198 flags |= VP8_EFLAG_NO_REF_ARF;
199 // Deliberately no break here.
200 FALLTHROUGH();
201 case kTemporalUpdateNone:
202 flags |= VP8_EFLAG_NO_UPD_GF;
203 flags |= VP8_EFLAG_NO_UPD_ARF;
204 flags |= VP8_EFLAG_NO_UPD_LAST;
205 flags |= VP8_EFLAG_NO_UPD_ENTROPY;
206 break;
207 case kTemporalUpdateNoneNoRefGoldenRefAltRef:
208 flags |= VP8_EFLAG_NO_REF_GF;
209 flags |= VP8_EFLAG_NO_UPD_GF;
210 flags |= VP8_EFLAG_NO_UPD_ARF;
211 flags |= VP8_EFLAG_NO_UPD_LAST;
212 flags |= VP8_EFLAG_NO_UPD_ENTROPY;
213 break;
214 case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
215 flags |= VP8_EFLAG_NO_REF_GF;
216 flags |= VP8_EFLAG_NO_UPD_ARF;
217 flags |= VP8_EFLAG_NO_UPD_LAST;
218 break;
219 case kTemporalUpdateLastRefAltRef:
220 flags |= VP8_EFLAG_NO_UPD_GF;
221 flags |= VP8_EFLAG_NO_UPD_ARF;
222 flags |= VP8_EFLAG_NO_REF_GF;
223 break;
224 case kTemporalUpdateGoldenRefAltRef:
225 flags |= VP8_EFLAG_NO_UPD_ARF;
226 flags |= VP8_EFLAG_NO_UPD_LAST;
227 break;
228 case kTemporalUpdateLastAndGoldenRefAltRef:
229 flags |= VP8_EFLAG_NO_UPD_ARF;
230 flags |= VP8_EFLAG_NO_REF_GF;
231 break;
232 case kTemporalUpdateLastRefAll:
233 flags |= VP8_EFLAG_NO_UPD_ARF;
234 flags |= VP8_EFLAG_NO_UPD_GF;
235 break;
236 }
237 return flags;
238 }
239
PopulateCodecSpecific(bool base_layer_sync,CodecSpecificInfoVP8 * vp8_info,uint32_t timestamp)240 void DefaultTemporalLayers::PopulateCodecSpecific(
241 bool base_layer_sync,
242 CodecSpecificInfoVP8* vp8_info,
243 uint32_t timestamp) {
244 assert(number_of_temporal_layers_ > 0);
245 assert(0 < temporal_ids_length_);
246
247 if (number_of_temporal_layers_ == 1) {
248 vp8_info->temporalIdx = kNoTemporalIdx;
249 vp8_info->layerSync = false;
250 vp8_info->tl0PicIdx = kNoTl0PicIdx;
251 } else {
252 if (base_layer_sync) {
253 vp8_info->temporalIdx = 0;
254 vp8_info->layerSync = true;
255 } else {
256 vp8_info->temporalIdx = CurrentLayerId();
257 TemporalReferences temporal_reference =
258 temporal_pattern_[pattern_idx_ % temporal_pattern_length_];
259
260 if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
261 temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
262 temporal_reference ==
263 kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
264 temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
265 (temporal_reference == kTemporalUpdateNone &&
266 number_of_temporal_layers_ == 4)) {
267 vp8_info->layerSync = true;
268 } else {
269 vp8_info->layerSync = false;
270 }
271 }
272 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
273 // Regardless of pattern the frame after a base layer sync will always
274 // be a layer sync.
275 vp8_info->layerSync = true;
276 }
277 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
278 timestamp_ = timestamp;
279 tl0_pic_idx_++;
280 }
281 last_base_layer_sync_ = base_layer_sync;
282 vp8_info->tl0PicIdx = tl0_pic_idx_;
283 }
284 }
285
Create(int temporal_layers,uint8_t initial_tl0_pic_idx) const286 TemporalLayers* TemporalLayers::Factory::Create(
287 int temporal_layers,
288 uint8_t initial_tl0_pic_idx) const {
289 return new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
290 }
291 } // namespace webrtc
292