• Home
  • 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/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