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> | |
13 #include <stdlib.h> | 12 #include <stdlib.h> |
14 #include <string.h> | 13 #include <string.h> |
15 | 14 |
16 #include <algorithm> | 15 #include <algorithm> |
17 #include <vector> | 16 #include <vector> |
18 | 17 |
19 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
20 #include "webrtc/modules/include/module_common_types.h" | 19 #include "webrtc/modules/include/module_common_types.h" |
21 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 20 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
22 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" | 21 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" |
23 | 22 |
24 #include "vpx/vpx_encoder.h" | 23 #include "vpx/vpx_encoder.h" |
25 #include "vpx/vp8cx.h" | 24 #include "vpx/vp8cx.h" |
26 | 25 |
27 namespace webrtc { | 26 namespace webrtc { |
28 | 27 |
| 28 TemporalReferences::TemporalReferences(TemporalBufferUsage last, |
| 29 TemporalBufferUsage golden, |
| 30 TemporalBufferUsage arf) |
| 31 : TemporalReferences(last, golden, arf, false, false) {} |
| 32 |
| 33 TemporalReferences::TemporalReferences(TemporalBufferUsage last, |
| 34 TemporalBufferUsage golden, |
| 35 TemporalBufferUsage arf, |
| 36 int extra_flags) |
| 37 : TemporalReferences(last, |
| 38 golden, |
| 39 arf, |
| 40 (extra_flags & kLayerSync) != 0, |
| 41 (extra_flags & kFreezeEntropy) != 0) {} |
| 42 |
| 43 TemporalReferences::TemporalReferences(TemporalBufferUsage last, |
| 44 TemporalBufferUsage golden, |
| 45 TemporalBufferUsage arf, |
| 46 bool layer_sync, |
| 47 bool freeze_entropy) |
| 48 : reference_last((last & kReference) != 0), |
| 49 update_last((last & kUpdate) != 0), |
| 50 reference_golden((golden & kReference) != 0), |
| 51 update_golden((golden & kUpdate) != 0), |
| 52 reference_arf((arf & kReference) != 0), |
| 53 update_arf((arf & kUpdate) != 0), |
| 54 layer_sync(layer_sync), |
| 55 freeze_entropy(freeze_entropy) {} |
| 56 |
| 57 namespace { |
| 58 |
| 59 std::vector<unsigned int> GetTemporalIds(size_t num_layers) { |
| 60 switch (num_layers) { |
| 61 case 1: |
| 62 // Temporal layer structure (single layer): |
| 63 // 0 0 0 0 ... |
| 64 return {0}; |
| 65 case 2: |
| 66 // Temporal layer structure: |
| 67 // 1 1 ... |
| 68 // 0 0 ... |
| 69 return {0, 1}; |
| 70 case 3: |
| 71 // Temporal layer structure: |
| 72 // 2 2 2 2 ... |
| 73 // 1 1 ... |
| 74 // 0 0 ... |
| 75 return {0, 2, 1, 2}; |
| 76 case 4: |
| 77 // Temporal layer structure: |
| 78 // 3 3 3 3 3 3 3 3 ... |
| 79 // 2 2 2 2 ... |
| 80 // 1 1 ... |
| 81 // 0 0 ... |
| 82 return {0, 3, 2, 3, 1, 3, 2, 3}; |
| 83 default: |
| 84 RTC_NOTREACHED(); |
| 85 break; |
| 86 } |
| 87 RTC_NOTREACHED(); |
| 88 return {0}; |
| 89 } |
| 90 |
| 91 std::vector<TemporalReferences> GetTemporalPattern( |
| 92 size_t num_layers) { |
| 93 // For indexing in the patterns described below (which temporal layers they |
| 94 // belong to), see the diagram above. |
| 95 // Layer sync is done similarly for all patterns (except single stream) and |
| 96 // happens every 8 frames: |
| 97 // TL1 layer syncs by periodically by only referencing TL0 ('last'), but still |
| 98 // updating 'golden', so it can be used as a reference by future TL1 frames. |
| 99 // TL2 layer syncs just before TL1 by only depending on TL0 (and not depending |
| 100 // on TL1's buffer before TL1 has layer synced). |
| 101 // TODO(pbos): Consider cyclically updating 'arf' (and 'golden' for 1TL) for |
| 102 // the base layer in 1-3TL instead of 'last' periodically on long intervals, |
| 103 // so that if scene changes occur (user walks between rooms or rotates webcam) |
| 104 // the 'arf' (or 'golden' respectively) is not stuck on a no-longer relevant |
| 105 // keyframe. |
| 106 switch (num_layers) { |
| 107 case 1: |
| 108 // All frames reference all buffers and the 'last' buffer is updated. |
| 109 return {TemporalReferences(kReferenceAndUpdate, kReference, kReference)}; |
| 110 case 2: |
| 111 // All layers can reference but not update the 'alt' buffer, this means |
| 112 // that the 'alt' buffer reference is effectively the last keyframe. |
| 113 // TL0 also references and updates the 'last' buffer. |
| 114 // TL1 also references 'last' and references and updates 'golden'. |
| 115 return {TemporalReferences(kReferenceAndUpdate, kUpdate, kReference), |
| 116 TemporalReferences(kReference, kUpdate, kReference, kLayerSync), |
| 117 TemporalReferences(kReferenceAndUpdate, kNone, kReference), |
| 118 TemporalReferences(kReference, kReferenceAndUpdate, kReference), |
| 119 TemporalReferences(kReferenceAndUpdate, kNone, kReference), |
| 120 TemporalReferences(kReference, kReferenceAndUpdate, kReference), |
| 121 TemporalReferences(kReferenceAndUpdate, kNone, kReference), |
| 122 TemporalReferences(kReference, kReference, kReference, |
| 123 kFreezeEntropy)}; |
| 124 case 3: |
| 125 // All layers can reference but not update the 'alt' buffer, this means |
| 126 // that the 'alt' buffer reference is effectively the last keyframe. |
| 127 // TL0 also references and updates the 'last' buffer. |
| 128 // TL1 also references 'last' and references and updates 'golden'. |
| 129 // TL2 references both 'last' and 'golden' but updates no buffer. |
| 130 return {TemporalReferences(kReferenceAndUpdate, kUpdate, kReference), |
| 131 TemporalReferences(kReference, kNone, kReference, |
| 132 kLayerSync | kFreezeEntropy), |
| 133 TemporalReferences(kReference, kUpdate, kReference, kLayerSync), |
| 134 TemporalReferences(kReference, kReference, kReference, |
| 135 kFreezeEntropy), |
| 136 TemporalReferences(kReferenceAndUpdate, kNone, kReference), |
| 137 TemporalReferences(kReference, kReference, kReference, |
| 138 kFreezeEntropy), |
| 139 TemporalReferences(kReference, kReferenceAndUpdate, kReference), |
| 140 TemporalReferences(kReference, kReference, kReference, |
| 141 kFreezeEntropy)}; |
| 142 case 4: |
| 143 // TL0 references and updates only the 'last' buffer. |
| 144 // TL1 references 'last' and updates and references 'golden'. |
| 145 // TL2 references 'last' and 'golden', and references and updates 'arf'. |
| 146 // TL3 references all buffers but update none of them. |
| 147 return {TemporalReferences(kReferenceAndUpdate, kNone, kNone), |
| 148 TemporalReferences(kReference, kReference, kReference, |
| 149 kLayerSync | kFreezeEntropy), |
| 150 TemporalReferences(kReference, kNone, kUpdate, kLayerSync), |
| 151 TemporalReferences(kReference, kReference, kReference, |
| 152 kLayerSync | kFreezeEntropy), |
| 153 TemporalReferences(kReference, kUpdate, kNone, kLayerSync), |
| 154 TemporalReferences(kReference, kReference, kReference, |
| 155 kLayerSync | kFreezeEntropy), |
| 156 TemporalReferences(kReference, kReference, kReferenceAndUpdate), |
| 157 TemporalReferences(kReference, kReference, kReference, |
| 158 kLayerSync | kFreezeEntropy), |
| 159 TemporalReferences(kReferenceAndUpdate, kNone, kNone), |
| 160 TemporalReferences(kReference, kReference, kReference, |
| 161 kLayerSync | kFreezeEntropy), |
| 162 TemporalReferences(kReference, kReference, kReferenceAndUpdate), |
| 163 TemporalReferences(kReference, kReference, kReference, |
| 164 kLayerSync | kFreezeEntropy), |
| 165 TemporalReferences(kReference, kReferenceAndUpdate, kNone), |
| 166 TemporalReferences(kReference, kReference, kReference, |
| 167 kLayerSync | kFreezeEntropy), |
| 168 TemporalReferences(kReference, kReference, kReferenceAndUpdate), |
| 169 TemporalReferences(kReference, kReference, kReference, |
| 170 kLayerSync | kFreezeEntropy)}; |
| 171 default: |
| 172 RTC_NOTREACHED(); |
| 173 break; |
| 174 } |
| 175 RTC_NOTREACHED(); |
| 176 return {TemporalReferences(kNone, kNone, kNone)}; |
| 177 } |
| 178 |
| 179 } // namespace |
| 180 |
29 DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers, | 181 DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers, |
30 uint8_t initial_tl0_pic_idx) | 182 uint8_t initial_tl0_pic_idx) |
31 : number_of_temporal_layers_(number_of_temporal_layers), | 183 : num_layers_(std::max(1, number_of_temporal_layers)), |
32 temporal_ids_length_(0), | 184 temporal_ids_(GetTemporalIds(num_layers_)), |
33 temporal_pattern_length_(0), | 185 temporal_pattern_(GetTemporalPattern(num_layers_)), |
34 tl0_pic_idx_(initial_tl0_pic_idx), | 186 tl0_pic_idx_(initial_tl0_pic_idx), |
35 pattern_idx_(255), | 187 pattern_idx_(255), |
36 timestamp_(0), | 188 timestamp_(0), |
37 last_base_layer_sync_(false) { | 189 last_base_layer_sync_(false) { |
38 RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers); | 190 RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers); |
39 RTC_CHECK_GE(number_of_temporal_layers, 0); | 191 RTC_CHECK_GE(number_of_temporal_layers, 0); |
40 memset(temporal_ids_, 0, sizeof(temporal_ids_)); | 192 RTC_CHECK_LE(number_of_temporal_layers, 4); |
41 memset(temporal_pattern_, 0, sizeof(temporal_pattern_)); | |
42 } | 193 } |
43 | 194 |
44 int DefaultTemporalLayers::CurrentLayerId() const { | 195 int DefaultTemporalLayers::CurrentLayerId() const { |
45 assert(temporal_ids_length_ > 0); | 196 return temporal_ids_[pattern_idx_ % temporal_ids_.size()]; |
46 int index = pattern_idx_ % temporal_ids_length_; | |
47 assert(index >= 0); | |
48 return temporal_ids_[index]; | |
49 } | 197 } |
50 | 198 |
51 std::vector<uint32_t> DefaultTemporalLayers::OnRatesUpdated( | 199 std::vector<uint32_t> DefaultTemporalLayers::OnRatesUpdated( |
52 int bitrate_kbps, | 200 int bitrate_kbps, |
53 int max_bitrate_kbps, | 201 int max_bitrate_kbps, |
54 int framerate) { | 202 int framerate) { |
55 std::vector<uint32_t> bitrates; | 203 std::vector<uint32_t> bitrates; |
56 const int num_layers = std::max(1, number_of_temporal_layers_); | 204 for (size_t i = 0; i < num_layers_; ++i) { |
57 for (int i = 0; i < num_layers; ++i) { | |
58 float layer_bitrate = | 205 float layer_bitrate = |
59 bitrate_kbps * kVp8LayerRateAlloction[num_layers - 1][i]; | 206 bitrate_kbps * kVp8LayerRateAlloction[num_layers_ - 1][i]; |
60 bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5)); | 207 bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5)); |
61 } | 208 } |
62 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates); | 209 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates); |
63 | 210 |
64 // Allocation table is of aggregates, transform to individual rates. | 211 // Allocation table is of aggregates, transform to individual rates. |
65 uint32_t sum = 0; | 212 uint32_t sum = 0; |
66 for (int i = 0; i < num_layers; ++i) { | 213 for (size_t i = 0; i < num_layers_; ++i) { |
67 uint32_t layer_bitrate = bitrates[i]; | 214 uint32_t layer_bitrate = bitrates[i]; |
68 RTC_DCHECK_LE(sum, bitrates[i]); | 215 RTC_DCHECK_LE(sum, bitrates[i]); |
69 bitrates[i] -= sum; | 216 bitrates[i] -= sum; |
70 sum = layer_bitrate; | 217 sum = layer_bitrate; |
71 | 218 |
72 if (sum >= static_cast<uint32_t>(bitrate_kbps)) { | 219 if (sum >= static_cast<uint32_t>(bitrate_kbps)) { |
73 // Sum adds up; any subsequent layers will be 0. | 220 // Sum adds up; any subsequent layers will be 0. |
74 bitrates.resize(i + 1); | 221 bitrates.resize(i + 1); |
75 break; | 222 break; |
76 } | 223 } |
77 } | 224 } |
78 | 225 |
79 return bitrates; | 226 return bitrates; |
80 } | 227 } |
81 | 228 |
82 bool DefaultTemporalLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { | 229 bool DefaultTemporalLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { |
83 if (!new_bitrates_kbps_) | 230 if (!new_bitrates_kbps_) |
84 return false; | 231 return false; |
85 | 232 |
86 switch (number_of_temporal_layers_) { | 233 for (size_t i = 0; i < num_layers_; ++i) { |
87 case 0: | 234 cfg->ts_target_bitrate[i] = (*new_bitrates_kbps_)[i]; |
88 FALLTHROUGH(); | 235 // ..., 4, 2, 1 |
89 case 1: | 236 cfg->ts_rate_decimator[i] = 1 << (num_layers_ - i - 1); |
90 temporal_ids_length_ = 1; | |
91 temporal_ids_[0] = 0; | |
92 cfg->ts_number_layers = number_of_temporal_layers_; | |
93 cfg->ts_periodicity = temporal_ids_length_; | |
94 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0]; | |
95 cfg->ts_rate_decimator[0] = 1; | |
96 memcpy(cfg->ts_layer_id, temporal_ids_, | |
97 sizeof(unsigned int) * temporal_ids_length_); | |
98 temporal_pattern_length_ = 1; | |
99 temporal_pattern_[0] = kTemporalUpdateLastRefAll; | |
100 break; | |
101 case 2: | |
102 temporal_ids_length_ = 2; | |
103 temporal_ids_[0] = 0; | |
104 temporal_ids_[1] = 1; | |
105 cfg->ts_number_layers = number_of_temporal_layers_; | |
106 cfg->ts_periodicity = temporal_ids_length_; | |
107 // Split stream 60% 40%. | |
108 // Bitrate API for VP8 is the agregated bitrate for all lower layers. | |
109 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0]; | |
110 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1]; | |
111 cfg->ts_rate_decimator[0] = 2; | |
112 cfg->ts_rate_decimator[1] = 1; | |
113 memcpy(cfg->ts_layer_id, temporal_ids_, | |
114 sizeof(unsigned int) * temporal_ids_length_); | |
115 temporal_pattern_length_ = 8; | |
116 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef; | |
117 temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; | |
118 temporal_pattern_[2] = kTemporalUpdateLastRefAltRef; | |
119 temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef; | |
120 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef; | |
121 temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef; | |
122 temporal_pattern_[6] = kTemporalUpdateLastRefAltRef; | |
123 temporal_pattern_[7] = kTemporalUpdateNone; | |
124 break; | |
125 case 3: | |
126 temporal_ids_length_ = 4; | |
127 temporal_ids_[0] = 0; | |
128 temporal_ids_[1] = 2; | |
129 temporal_ids_[2] = 1; | |
130 temporal_ids_[3] = 2; | |
131 cfg->ts_number_layers = number_of_temporal_layers_; | |
132 cfg->ts_periodicity = temporal_ids_length_; | |
133 // Split stream 40% 20% 40%. | |
134 // Bitrate API for VP8 is the agregated bitrate for all lower layers. | |
135 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0]; | |
136 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1]; | |
137 cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2]; | |
138 cfg->ts_rate_decimator[0] = 4; | |
139 cfg->ts_rate_decimator[1] = 2; | |
140 cfg->ts_rate_decimator[2] = 1; | |
141 memcpy(cfg->ts_layer_id, temporal_ids_, | |
142 sizeof(unsigned int) * temporal_ids_length_); | |
143 temporal_pattern_length_ = 8; | |
144 temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef; | |
145 temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef; | |
146 temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef; | |
147 temporal_pattern_[3] = kTemporalUpdateNone; | |
148 temporal_pattern_[4] = kTemporalUpdateLastRefAltRef; | |
149 temporal_pattern_[5] = kTemporalUpdateNone; | |
150 temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef; | |
151 temporal_pattern_[7] = kTemporalUpdateNone; | |
152 break; | |
153 case 4: | |
154 temporal_ids_length_ = 8; | |
155 temporal_ids_[0] = 0; | |
156 temporal_ids_[1] = 3; | |
157 temporal_ids_[2] = 2; | |
158 temporal_ids_[3] = 3; | |
159 temporal_ids_[4] = 1; | |
160 temporal_ids_[5] = 3; | |
161 temporal_ids_[6] = 2; | |
162 temporal_ids_[7] = 3; | |
163 // Split stream 25% 15% 20% 40%. | |
164 // Bitrate API for VP8 is the agregated bitrate for all lower layers. | |
165 cfg->ts_number_layers = 4; | |
166 cfg->ts_periodicity = temporal_ids_length_; | |
167 cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0]; | |
168 cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1]; | |
169 cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2]; | |
170 cfg->ts_target_bitrate[3] = (*new_bitrates_kbps_)[3]; | |
171 cfg->ts_rate_decimator[0] = 8; | |
172 cfg->ts_rate_decimator[1] = 4; | |
173 cfg->ts_rate_decimator[2] = 2; | |
174 cfg->ts_rate_decimator[3] = 1; | |
175 memcpy(cfg->ts_layer_id, temporal_ids_, | |
176 sizeof(unsigned int) * temporal_ids_length_); | |
177 temporal_pattern_length_ = 16; | |
178 temporal_pattern_[0] = kTemporalUpdateLast; | |
179 temporal_pattern_[1] = kTemporalUpdateNone; | |
180 temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency; | |
181 temporal_pattern_[3] = kTemporalUpdateNone; | |
182 temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency; | |
183 temporal_pattern_[5] = kTemporalUpdateNone; | |
184 temporal_pattern_[6] = kTemporalUpdateAltref; | |
185 temporal_pattern_[7] = kTemporalUpdateNone; | |
186 temporal_pattern_[8] = kTemporalUpdateLast; | |
187 temporal_pattern_[9] = kTemporalUpdateNone; | |
188 temporal_pattern_[10] = kTemporalUpdateAltref; | |
189 temporal_pattern_[11] = kTemporalUpdateNone; | |
190 temporal_pattern_[12] = kTemporalUpdateGolden; | |
191 temporal_pattern_[13] = kTemporalUpdateNone; | |
192 temporal_pattern_[14] = kTemporalUpdateAltref; | |
193 temporal_pattern_[15] = kTemporalUpdateNone; | |
194 break; | |
195 default: | |
196 RTC_NOTREACHED(); | |
197 return false; | |
198 } | 237 } |
199 | 238 |
| 239 cfg->ts_number_layers = num_layers_; |
| 240 cfg->ts_periodicity = temporal_ids_.size(); |
| 241 memcpy(cfg->ts_layer_id, &temporal_ids_[0], |
| 242 sizeof(unsigned int) * temporal_ids_.size()); |
| 243 |
200 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(); | 244 new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(); |
201 | 245 |
202 return true; | 246 return true; |
203 } | 247 } |
204 | 248 |
205 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) { | 249 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) { |
206 assert(number_of_temporal_layers_ > 0); | 250 RTC_DCHECK_GT(num_layers_, 0); |
207 assert(kMaxTemporalPattern >= temporal_pattern_length_); | 251 RTC_DCHECK_LT(0, temporal_pattern_.size()); |
208 assert(0 < temporal_pattern_length_); | |
209 int flags = 0; | 252 int flags = 0; |
210 int patternIdx = ++pattern_idx_ % temporal_pattern_length_; | 253 // TODO(pbos): Move pattern-update out of EncodeFlags. It's not obvious that |
211 assert(kMaxTemporalPattern >= patternIdx); | 254 // EncodeFlags() is non-const. |
212 switch (temporal_pattern_[patternIdx]) { | 255 const TemporalReferences& references = |
213 case kTemporalUpdateLast: | 256 temporal_pattern_[++pattern_idx_ % temporal_pattern_.size()]; |
214 flags |= VP8_EFLAG_NO_UPD_GF; | 257 |
215 flags |= VP8_EFLAG_NO_UPD_ARF; | 258 if (!references.reference_last) |
216 flags |= VP8_EFLAG_NO_REF_GF; | 259 flags |= VP8_EFLAG_NO_REF_LAST; |
217 flags |= VP8_EFLAG_NO_REF_ARF; | 260 if (!references.update_last) |
218 break; | 261 flags |= VP8_EFLAG_NO_UPD_LAST; |
219 case kTemporalUpdateGoldenWithoutDependency: | 262 if (!references.reference_golden) |
220 flags |= VP8_EFLAG_NO_REF_GF; | 263 flags |= VP8_EFLAG_NO_REF_GF; |
221 // Deliberately no break here. | 264 if (!references.update_golden) |
222 FALLTHROUGH(); | 265 flags |= VP8_EFLAG_NO_UPD_GF; |
223 case kTemporalUpdateGolden: | 266 if (!references.reference_arf) |
224 flags |= VP8_EFLAG_NO_REF_ARF; | 267 flags |= VP8_EFLAG_NO_REF_ARF; |
225 flags |= VP8_EFLAG_NO_UPD_ARF; | 268 if (!references.update_arf) |
226 flags |= VP8_EFLAG_NO_UPD_LAST; | 269 flags |= VP8_EFLAG_NO_UPD_ARF; |
227 break; | 270 if (references.freeze_entropy) |
228 case kTemporalUpdateAltrefWithoutDependency: | 271 flags |= VP8_EFLAG_NO_UPD_ENTROPY; |
229 flags |= VP8_EFLAG_NO_REF_ARF; | 272 |
230 flags |= VP8_EFLAG_NO_REF_GF; | |
231 // Deliberately no break here. | |
232 FALLTHROUGH(); | |
233 case kTemporalUpdateAltref: | |
234 flags |= VP8_EFLAG_NO_UPD_GF; | |
235 flags |= VP8_EFLAG_NO_UPD_LAST; | |
236 break; | |
237 case kTemporalUpdateNoneNoRefAltref: | |
238 flags |= VP8_EFLAG_NO_REF_ARF; | |
239 // Deliberately no break here. | |
240 FALLTHROUGH(); | |
241 case kTemporalUpdateNone: | |
242 flags |= VP8_EFLAG_NO_UPD_GF; | |
243 flags |= VP8_EFLAG_NO_UPD_ARF; | |
244 flags |= VP8_EFLAG_NO_UPD_LAST; | |
245 flags |= VP8_EFLAG_NO_UPD_ENTROPY; | |
246 break; | |
247 case kTemporalUpdateNoneNoRefGoldenRefAltRef: | |
248 flags |= VP8_EFLAG_NO_REF_GF; | |
249 flags |= VP8_EFLAG_NO_UPD_GF; | |
250 flags |= VP8_EFLAG_NO_UPD_ARF; | |
251 flags |= VP8_EFLAG_NO_UPD_LAST; | |
252 flags |= VP8_EFLAG_NO_UPD_ENTROPY; | |
253 break; | |
254 case kTemporalUpdateGoldenWithoutDependencyRefAltRef: | |
255 flags |= VP8_EFLAG_NO_REF_GF; | |
256 flags |= VP8_EFLAG_NO_UPD_ARF; | |
257 flags |= VP8_EFLAG_NO_UPD_LAST; | |
258 break; | |
259 case kTemporalUpdateLastRefAltRef: | |
260 flags |= VP8_EFLAG_NO_UPD_GF; | |
261 flags |= VP8_EFLAG_NO_UPD_ARF; | |
262 flags |= VP8_EFLAG_NO_REF_GF; | |
263 break; | |
264 case kTemporalUpdateGoldenRefAltRef: | |
265 flags |= VP8_EFLAG_NO_UPD_ARF; | |
266 flags |= VP8_EFLAG_NO_UPD_LAST; | |
267 break; | |
268 case kTemporalUpdateLastAndGoldenRefAltRef: | |
269 flags |= VP8_EFLAG_NO_UPD_ARF; | |
270 flags |= VP8_EFLAG_NO_REF_GF; | |
271 break; | |
272 case kTemporalUpdateLastRefAll: | |
273 flags |= VP8_EFLAG_NO_UPD_ARF; | |
274 flags |= VP8_EFLAG_NO_UPD_GF; | |
275 break; | |
276 } | |
277 return flags; | 273 return flags; |
278 } | 274 } |
279 | 275 |
280 void DefaultTemporalLayers::PopulateCodecSpecific( | 276 void DefaultTemporalLayers::PopulateCodecSpecific( |
281 bool base_layer_sync, | 277 bool base_layer_sync, |
282 CodecSpecificInfoVP8* vp8_info, | 278 CodecSpecificInfoVP8* vp8_info, |
283 uint32_t timestamp) { | 279 uint32_t timestamp) { |
284 assert(number_of_temporal_layers_ > 0); | 280 RTC_DCHECK_GT(num_layers_, 0); |
285 assert(0 < temporal_ids_length_); | |
286 | 281 |
287 if (number_of_temporal_layers_ == 1) { | 282 if (num_layers_ == 1) { |
288 vp8_info->temporalIdx = kNoTemporalIdx; | 283 vp8_info->temporalIdx = kNoTemporalIdx; |
289 vp8_info->layerSync = false; | 284 vp8_info->layerSync = false; |
290 vp8_info->tl0PicIdx = kNoTl0PicIdx; | 285 vp8_info->tl0PicIdx = kNoTl0PicIdx; |
291 } else { | 286 } else { |
292 if (base_layer_sync) { | 287 if (base_layer_sync) { |
293 vp8_info->temporalIdx = 0; | 288 vp8_info->temporalIdx = 0; |
294 vp8_info->layerSync = true; | 289 vp8_info->layerSync = true; |
295 } else { | 290 } else { |
296 vp8_info->temporalIdx = CurrentLayerId(); | 291 vp8_info->temporalIdx = CurrentLayerId(); |
297 TemporalReferences temporal_reference = | 292 TemporalReferences temporal_reference = |
298 temporal_pattern_[pattern_idx_ % temporal_pattern_length_]; | 293 temporal_pattern_[pattern_idx_ % temporal_pattern_.size()]; |
299 | 294 |
300 if (temporal_reference == kTemporalUpdateAltrefWithoutDependency || | 295 vp8_info->layerSync = temporal_reference.layer_sync; |
301 temporal_reference == kTemporalUpdateGoldenWithoutDependency || | |
302 temporal_reference == | |
303 kTemporalUpdateGoldenWithoutDependencyRefAltRef || | |
304 temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef || | |
305 (temporal_reference == kTemporalUpdateNone && | |
306 number_of_temporal_layers_ == 4)) { | |
307 vp8_info->layerSync = true; | |
308 } else { | |
309 vp8_info->layerSync = false; | |
310 } | |
311 } | 296 } |
312 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { | 297 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { |
313 // Regardless of pattern the frame after a base layer sync will always | 298 // Regardless of pattern the frame after a base layer sync will always |
314 // be a layer sync. | 299 // be a layer sync. |
315 vp8_info->layerSync = true; | 300 vp8_info->layerSync = true; |
316 } | 301 } |
317 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { | 302 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { |
318 timestamp_ = timestamp; | 303 timestamp_ = timestamp; |
319 tl0_pic_idx_++; | 304 tl0_pic_idx_++; |
320 } | 305 } |
(...skipping 11 matching lines...) Expand all Loading... |
332 if (listener_) | 317 if (listener_) |
333 listener_->OnTemporalLayersCreated(simulcast_id, tl); | 318 listener_->OnTemporalLayersCreated(simulcast_id, tl); |
334 return tl; | 319 return tl; |
335 } | 320 } |
336 | 321 |
337 void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) { | 322 void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) { |
338 listener_ = listener; | 323 listener_ = listener; |
339 } | 324 } |
340 | 325 |
341 } // namespace webrtc | 326 } // namespace webrtc |
OLD | NEW |