OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |