• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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