Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc

Issue 2434073003: Extract bitrate allocation of spatial/temporal layers out of codec impl. (Closed)
Patch Set: Addressed comments. Moved VideoCodec creation to factory class. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
2 * 2 *
3 * Use of this source code is governed by a BSD-style license 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 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 5 * tree. An additional intellectual property rights grant can be found
6 * in the file PATENTS. All contributing project authors may 6 * in the file PATENTS. All contributing project authors may
7 * be found in the AUTHORS file in the root of the source tree. 7 * be found in the AUTHORS file in the root of the source tree.
8 */ 8 */
9 9
10 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" 10 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h"
11 11
12 #include <assert.h> 12 #include <assert.h>
13 #include <stdlib.h> 13 #include <stdlib.h>
14 #include <string.h> 14 #include <string.h>
15 15
16 #include <algorithm>
17 #include <vector>
18
19 #include "webrtc/base/checks.h"
16 #include "webrtc/modules/include/module_common_types.h" 20 #include "webrtc/modules/include/module_common_types.h"
17 #include "webrtc/modules/video_coding/include/video_codec_interface.h" 21 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
18 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 22 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
19 23
20 #include "vpx/vpx_encoder.h" 24 #include "vpx/vpx_encoder.h"
21 #include "vpx/vp8cx.h" 25 #include "vpx/vp8cx.h"
22 26
23 namespace webrtc { 27 namespace webrtc {
24 28
25 DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers, 29 DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers,
stefan-webrtc 2016/11/02 10:26:35 Please update this to non_camel_case
sprang_webrtc 2016/11/02 13:28:32 Done.
26 uint8_t initial_tl0_pic_idx) 30 uint8_t initial_tl0_pic_idx)
27 : number_of_temporal_layers_(numberOfTemporalLayers), 31 : number_of_temporal_layers_(numberOfTemporalLayers),
28 temporal_ids_length_(0), 32 temporal_ids_length_(0),
29 temporal_pattern_length_(0), 33 temporal_pattern_length_(0),
30 tl0_pic_idx_(initial_tl0_pic_idx), 34 tl0_pic_idx_(initial_tl0_pic_idx),
31 pattern_idx_(255), 35 pattern_idx_(255),
32 timestamp_(0), 36 timestamp_(0),
33 last_base_layer_sync_(false) { 37 last_base_layer_sync_(false) {
34 assert(kMaxTemporalStreams >= numberOfTemporalLayers); 38 RTC_CHECK_GE(kMaxTemporalStreams, numberOfTemporalLayers);
39 RTC_CHECK_GE(numberOfTemporalLayers, 0);
35 memset(temporal_ids_, 0, sizeof(temporal_ids_)); 40 memset(temporal_ids_, 0, sizeof(temporal_ids_));
36 memset(temporal_pattern_, 0, sizeof(temporal_pattern_)); 41 memset(temporal_pattern_, 0, sizeof(temporal_pattern_));
37 } 42 }
38 43
39 int DefaultTemporalLayers::CurrentLayerId() const { 44 int DefaultTemporalLayers::CurrentLayerId() const {
40 assert(temporal_ids_length_ > 0); 45 assert(temporal_ids_length_ > 0);
41 int index = pattern_idx_ % temporal_ids_length_; 46 int index = pattern_idx_ % temporal_ids_length_;
42 assert(index >= 0); 47 assert(index >= 0);
43 return temporal_ids_[index]; 48 return temporal_ids_[index];
44 } 49 }
45 50
46 bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit, 51 std::vector<uint32_t> DefaultTemporalLayers::OnRatesUpdated(
47 int max_bitrate_kbit, 52 int bitrateKbit,
stefan-webrtc 2016/11/02 10:26:35 Here too please :) Perhaps also change to kbps ins
sprang_webrtc 2016/11/02 13:28:32 Done.
48 int framerate, 53 int max_bitrate_kbit,
49 vpx_codec_enc_cfg_t* cfg) { 54 int framerate) {
55 std::vector<uint32_t> bitrates;
56 const int num_layers = std::max(1, number_of_temporal_layers_);
57 for (int i = 0; i < num_layers; ++i) {
58 float layer_bitrate =
59 bitrateKbit * kVp8LayerRateAlloction[num_layers - 1][i];
60 bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5));
61 }
62 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates);
63
64 // Allocation table is of aggregates, transform to individual rates.
65 uint32_t sum = 0;
66 for (int i = 0; i < num_layers; ++i) {
67 uint32_t layer_bitrate = bitrates[i];
68 bitrates[i] -= sum;
stefan-webrtc 2016/11/02 10:26:35 DCHECK that bitrates[i] > 0 after the subtraction,
sprang_webrtc 2016/11/02 13:28:32 Done.
69 sum = layer_bitrate;
70
71 if (sum >= static_cast<uint32_t>(bitrateKbit)) {
72 // Sum adds up; any subsequent layers will be 0.
73 bitrates.resize(i + 1);
74 break;
75 }
76 }
77
78 return bitrates;
79 }
80
81 bool DefaultTemporalLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
82 if (!new_bitrates_kbps_)
83 return false;
84
50 switch (number_of_temporal_layers_) { 85 switch (number_of_temporal_layers_) {
51 case 0: 86 case 0:
87 FALLTHROUGH();
52 case 1: 88 case 1:
53 temporal_ids_length_ = 1; 89 temporal_ids_length_ = 1;
54 temporal_ids_[0] = 0; 90 temporal_ids_[0] = 0;
55 cfg->ts_number_layers = number_of_temporal_layers_; 91 cfg->ts_number_layers = number_of_temporal_layers_;
56 cfg->ts_periodicity = temporal_ids_length_; 92 cfg->ts_periodicity = temporal_ids_length_;
57 cfg->ts_target_bitrate[0] = bitrateKbit; 93 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
stefan-webrtc 2016/11/02 10:26:35 Should we call this current_allocation_kbps_ or cu
sprang_webrtc 2016/11/02 13:28:32 They are new bitrates though, as the encoder has n
58 cfg->ts_rate_decimator[0] = 1; 94 cfg->ts_rate_decimator[0] = 1;
59 memcpy(cfg->ts_layer_id, temporal_ids_, 95 memcpy(cfg->ts_layer_id, temporal_ids_,
60 sizeof(unsigned int) * temporal_ids_length_); 96 sizeof(unsigned int) * temporal_ids_length_);
61 temporal_pattern_length_ = 1; 97 temporal_pattern_length_ = 1;
62 temporal_pattern_[0] = kTemporalUpdateLastRefAll; 98 temporal_pattern_[0] = kTemporalUpdateLastRefAll;
63 break; 99 break;
64 case 2: 100 case 2:
65 temporal_ids_length_ = 2; 101 temporal_ids_length_ = 2;
66 temporal_ids_[0] = 0; 102 temporal_ids_[0] = 0;
67 temporal_ids_[1] = 1; 103 temporal_ids_[1] = 1;
68 cfg->ts_number_layers = number_of_temporal_layers_; 104 cfg->ts_number_layers = number_of_temporal_layers_;
69 cfg->ts_periodicity = temporal_ids_length_; 105 cfg->ts_periodicity = temporal_ids_length_;
70 // Split stream 60% 40%. 106 // Split stream 60% 40%.
71 // Bitrate API for VP8 is the agregated bitrate for all lower layers. 107 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
72 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[1][0]; 108 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
73 cfg->ts_target_bitrate[1] = bitrateKbit; 109 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
74 cfg->ts_rate_decimator[0] = 2; 110 cfg->ts_rate_decimator[0] = 2;
75 cfg->ts_rate_decimator[1] = 1; 111 cfg->ts_rate_decimator[1] = 1;
76 memcpy(cfg->ts_layer_id, temporal_ids_, 112 memcpy(cfg->ts_layer_id, temporal_ids_,
77 sizeof(unsigned int) * temporal_ids_length_); 113 sizeof(unsigned int) * temporal_ids_length_);
78 temporal_pattern_length_ = 8; 114 temporal_pattern_length_ = 8;
79 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef; 115 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
80 temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 116 temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
81 temporal_pattern_[2] = kTemporalUpdateLastRefAltRef; 117 temporal_pattern_[2] = kTemporalUpdateLastRefAltRef;
82 temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef; 118 temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef;
83 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef; 119 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
84 temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef; 120 temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef;
85 temporal_pattern_[6] = kTemporalUpdateLastRefAltRef; 121 temporal_pattern_[6] = kTemporalUpdateLastRefAltRef;
86 temporal_pattern_[7] = kTemporalUpdateNone; 122 temporal_pattern_[7] = kTemporalUpdateNone;
87 break; 123 break;
88 case 3: 124 case 3:
89 temporal_ids_length_ = 4; 125 temporal_ids_length_ = 4;
90 temporal_ids_[0] = 0; 126 temporal_ids_[0] = 0;
91 temporal_ids_[1] = 2; 127 temporal_ids_[1] = 2;
92 temporal_ids_[2] = 1; 128 temporal_ids_[2] = 1;
93 temporal_ids_[3] = 2; 129 temporal_ids_[3] = 2;
94 cfg->ts_number_layers = number_of_temporal_layers_; 130 cfg->ts_number_layers = number_of_temporal_layers_;
95 cfg->ts_periodicity = temporal_ids_length_; 131 cfg->ts_periodicity = temporal_ids_length_;
96 // Split stream 40% 20% 40%. 132 // Split stream 40% 20% 40%.
97 // Bitrate API for VP8 is the agregated bitrate for all lower layers. 133 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
98 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[2][0]; 134 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
99 cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[2][1]; 135 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
100 cfg->ts_target_bitrate[2] = bitrateKbit; 136 cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
101 cfg->ts_rate_decimator[0] = 4; 137 cfg->ts_rate_decimator[0] = 4;
102 cfg->ts_rate_decimator[1] = 2; 138 cfg->ts_rate_decimator[1] = 2;
103 cfg->ts_rate_decimator[2] = 1; 139 cfg->ts_rate_decimator[2] = 1;
104 memcpy(cfg->ts_layer_id, temporal_ids_, 140 memcpy(cfg->ts_layer_id, temporal_ids_,
105 sizeof(unsigned int) * temporal_ids_length_); 141 sizeof(unsigned int) * temporal_ids_length_);
106 temporal_pattern_length_ = 8; 142 temporal_pattern_length_ = 8;
107 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef; 143 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
108 temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef; 144 temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
109 temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; 145 temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
110 temporal_pattern_[3] = kTemporalUpdateNone; 146 temporal_pattern_[3] = kTemporalUpdateNone;
111 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef; 147 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
112 temporal_pattern_[5] = kTemporalUpdateNone; 148 temporal_pattern_[5] = kTemporalUpdateNone;
113 temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef; 149 temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef;
114 temporal_pattern_[7] = kTemporalUpdateNone; 150 temporal_pattern_[7] = kTemporalUpdateNone;
115 break; 151 break;
116 case 4: 152 case 4:
117 temporal_ids_length_ = 8; 153 temporal_ids_length_ = 8;
118 temporal_ids_[0] = 0; 154 temporal_ids_[0] = 0;
119 temporal_ids_[1] = 3; 155 temporal_ids_[1] = 3;
120 temporal_ids_[2] = 2; 156 temporal_ids_[2] = 2;
121 temporal_ids_[3] = 3; 157 temporal_ids_[3] = 3;
122 temporal_ids_[4] = 1; 158 temporal_ids_[4] = 1;
123 temporal_ids_[5] = 3; 159 temporal_ids_[5] = 3;
124 temporal_ids_[6] = 2; 160 temporal_ids_[6] = 2;
125 temporal_ids_[7] = 3; 161 temporal_ids_[7] = 3;
126 // Split stream 25% 15% 20% 40%. 162 // Split stream 25% 15% 20% 40%.
127 // Bitrate API for VP8 is the agregated bitrate for all lower layers. 163 // Bitrate API for VP8 is the agregated bitrate for all lower layers.
128 cfg->ts_number_layers = 4; 164 cfg->ts_number_layers = 4;
129 cfg->ts_periodicity = temporal_ids_length_; 165 cfg->ts_periodicity = temporal_ids_length_;
130 cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[3][0]; 166 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
131 cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[3][1]; 167 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
132 cfg->ts_target_bitrate[2] = bitrateKbit * kVp8LayerRateAlloction[3][2]; 168 cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
133 cfg->ts_target_bitrate[3] = bitrateKbit; 169 cfg->ts_target_bitrate[3] = (*new_bitrates_kbps_)[3];
134 cfg->ts_rate_decimator[0] = 8; 170 cfg->ts_rate_decimator[0] = 8;
135 cfg->ts_rate_decimator[1] = 4; 171 cfg->ts_rate_decimator[1] = 4;
136 cfg->ts_rate_decimator[2] = 2; 172 cfg->ts_rate_decimator[2] = 2;
137 cfg->ts_rate_decimator[3] = 1; 173 cfg->ts_rate_decimator[3] = 1;
138 memcpy(cfg->ts_layer_id, temporal_ids_, 174 memcpy(cfg->ts_layer_id, temporal_ids_,
139 sizeof(unsigned int) * temporal_ids_length_); 175 sizeof(unsigned int) * temporal_ids_length_);
140 temporal_pattern_length_ = 16; 176 temporal_pattern_length_ = 16;
141 temporal_pattern_[0] = kTemporalUpdateLast; 177 temporal_pattern_[0] = kTemporalUpdateLast;
142 temporal_pattern_[1] = kTemporalUpdateNone; 178 temporal_pattern_[1] = kTemporalUpdateNone;
143 temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency; 179 temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency;
144 temporal_pattern_[3] = kTemporalUpdateNone; 180 temporal_pattern_[3] = kTemporalUpdateNone;
145 temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency; 181 temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency;
146 temporal_pattern_[5] = kTemporalUpdateNone; 182 temporal_pattern_[5] = kTemporalUpdateNone;
147 temporal_pattern_[6] = kTemporalUpdateAltref; 183 temporal_pattern_[6] = kTemporalUpdateAltref;
148 temporal_pattern_[7] = kTemporalUpdateNone; 184 temporal_pattern_[7] = kTemporalUpdateNone;
149 temporal_pattern_[8] = kTemporalUpdateLast; 185 temporal_pattern_[8] = kTemporalUpdateLast;
150 temporal_pattern_[9] = kTemporalUpdateNone; 186 temporal_pattern_[9] = kTemporalUpdateNone;
151 temporal_pattern_[10] = kTemporalUpdateAltref; 187 temporal_pattern_[10] = kTemporalUpdateAltref;
152 temporal_pattern_[11] = kTemporalUpdateNone; 188 temporal_pattern_[11] = kTemporalUpdateNone;
153 temporal_pattern_[12] = kTemporalUpdateGolden; 189 temporal_pattern_[12] = kTemporalUpdateGolden;
154 temporal_pattern_[13] = kTemporalUpdateNone; 190 temporal_pattern_[13] = kTemporalUpdateNone;
155 temporal_pattern_[14] = kTemporalUpdateAltref; 191 temporal_pattern_[14] = kTemporalUpdateAltref;
156 temporal_pattern_[15] = kTemporalUpdateNone; 192 temporal_pattern_[15] = kTemporalUpdateNone;
157 break; 193 break;
158 default: 194 default:
159 assert(false); 195 RTC_NOTREACHED();
160 return false; 196 return false;
161 } 197 }
198
199 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
stefan-webrtc 2016/11/02 10:26:35 Why is this needed?
sprang_webrtc 2016/11/02 13:28:32 To not have to redo all this work for every frame.
stefan-webrtc 2016/11/03 13:34:58 Acknowledged.
200
162 return true; 201 return true;
163 } 202 }
164 203
165 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) { 204 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) {
166 assert(number_of_temporal_layers_ > 0); 205 assert(number_of_temporal_layers_ > 0);
167 assert(kMaxTemporalPattern >= temporal_pattern_length_); 206 assert(kMaxTemporalPattern >= temporal_pattern_length_);
168 assert(0 < temporal_pattern_length_); 207 assert(0 < temporal_pattern_length_);
169 int flags = 0; 208 int flags = 0;
170 int patternIdx = ++pattern_idx_ % temporal_pattern_length_; 209 int patternIdx = ++pattern_idx_ % temporal_pattern_length_;
171 assert(kMaxTemporalPattern >= patternIdx); 210 assert(kMaxTemporalPattern >= patternIdx);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { 316 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
278 timestamp_ = timestamp; 317 timestamp_ = timestamp;
279 tl0_pic_idx_++; 318 tl0_pic_idx_++;
280 } 319 }
281 last_base_layer_sync_ = base_layer_sync; 320 last_base_layer_sync_ = base_layer_sync;
282 vp8_info->tl0PicIdx = tl0_pic_idx_; 321 vp8_info->tl0PicIdx = tl0_pic_idx_;
283 } 322 }
284 } 323 }
285 324
286 TemporalLayers* TemporalLayersFactory::Create( 325 TemporalLayers* TemporalLayersFactory::Create(
326 int simulcast_id,
287 int temporal_layers, 327 int temporal_layers,
288 uint8_t initial_tl0_pic_idx) const { 328 uint8_t initial_tl0_pic_idx) const {
289 return new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx); 329 TemporalLayers* tl =
330 new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
331 if (listener_)
332 listener_->OnTemporalLayersCreated(simulcast_id, tl);
333 return tl;
290 } 334 }
335
336 void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) {
337 listener_ = listener;
338 }
339
291 } // namespace webrtc 340 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698