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