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/screenshare_layers.h" | 10 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. | 140 // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction. |
141 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. | 141 // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate. |
142 target_bitrate_kbps = | 142 target_bitrate_kbps = |
143 std::min(bitrate_kbps * kMaxTL0FpsReduction, | 143 std::min(bitrate_kbps * kMaxTL0FpsReduction, |
144 max_bitrate_kbps / kAcceptableTargetOvershoot); | 144 max_bitrate_kbps / kAcceptableTargetOvershoot); |
145 | 145 |
146 cfg->rc_target_bitrate = std::max(bitrate_kbps, target_bitrate_kbps); | 146 cfg->rc_target_bitrate = std::max(bitrate_kbps, target_bitrate_kbps); |
147 } | 147 } |
148 | 148 |
149 // Don't reconfigure qp limits during quality boost frames. | 149 // Don't reconfigure qp limits during quality boost frames. |
150 if (layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { | 150 if (active_layer_ != -1 && |
pbos-webrtc
2016/02/02 21:16:14
Can you amend the comment above to include what -1
sprang
2016/02/03 10:05:37
Done.
| |
151 layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) { | |
151 min_qp_ = cfg->rc_min_quantizer; | 152 min_qp_ = cfg->rc_min_quantizer; |
152 max_qp_ = cfg->rc_max_quantizer; | 153 max_qp_ = cfg->rc_max_quantizer; |
153 // After a dropped frame, a frame with max qp will be encoded and the | 154 // After a dropped frame, a frame with max qp will be encoded and the |
154 // quality will then ramp up from there. To boost the speed of recovery, | 155 // quality will then ramp up from there. To boost the speed of recovery, |
155 // encode the next frame with lower max qp. TL0 is the most important to | 156 // encode the next frame with lower max qp. TL0 is the most important to |
156 // improve since the errors in this layer will propagate to TL1. | 157 // improve since the errors in this layer will propagate to TL1. |
157 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. | 158 // Currently, reduce max qp by 20% for TL0 and 15% for TL1. |
158 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); | 159 layers_[0].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 80) / 100); |
159 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); | 160 layers_[1].enhanced_max_qp = min_qp_ + (((max_qp_ - min_qp_) * 85) / 100); |
160 } | 161 } |
161 } | 162 } |
162 | 163 |
163 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate); | 164 int avg_frame_size = (target_bitrate_kbps * 1000) / (8 * framerate); |
164 max_debt_bytes_ = 4 * avg_frame_size; | 165 max_debt_bytes_ = 4 * avg_frame_size; |
165 | 166 |
166 return true; | 167 return true; |
167 } | 168 } |
168 | 169 |
169 void ScreenshareLayers::FrameEncoded(unsigned int size, | 170 void ScreenshareLayers::FrameEncoded(unsigned int size, |
170 uint32_t timestamp, | 171 uint32_t timestamp, |
171 int qp) { | 172 int qp) { |
173 RTC_DCHECK_NE(-1, active_layer_); | |
172 if (size == 0) { | 174 if (size == 0) { |
173 layers_[active_layer_].state = TemporalLayer::State::kDropped; | 175 layers_[active_layer_].state = TemporalLayer::State::kDropped; |
174 return; | 176 return; |
175 } | 177 } |
176 | 178 |
177 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) { | 179 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) { |
178 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost; | 180 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost; |
179 } | 181 } |
180 | 182 |
181 if (qp != -1) | 183 if (qp != -1) |
182 layers_[active_layer_].last_qp = qp; | 184 layers_[active_layer_].last_qp = qp; |
183 | 185 |
184 if (active_layer_ == 0) { | 186 if (active_layer_ == 0) { |
185 layers_[0].debt_bytes_ += size; | 187 layers_[0].debt_bytes_ += size; |
186 layers_[1].debt_bytes_ += size; | 188 layers_[1].debt_bytes_ += size; |
187 } else if (active_layer_ == 1) { | 189 } else if (active_layer_ == 1) { |
188 layers_[1].debt_bytes_ += size; | 190 layers_[1].debt_bytes_ += size; |
189 } | 191 } |
190 } | 192 } |
191 | 193 |
192 void ScreenshareLayers::PopulateCodecSpecific(bool base_layer_sync, | 194 void ScreenshareLayers::PopulateCodecSpecific(bool base_layer_sync, |
193 CodecSpecificInfoVP8* vp8_info, | 195 CodecSpecificInfoVP8* vp8_info, |
194 uint32_t timestamp) { | 196 uint32_t timestamp) { |
195 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); | 197 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
196 if (number_of_temporal_layers_ == 1) { | 198 if (number_of_temporal_layers_ == 1) { |
197 vp8_info->temporalIdx = kNoTemporalIdx; | 199 vp8_info->temporalIdx = kNoTemporalIdx; |
198 vp8_info->layerSync = false; | 200 vp8_info->layerSync = false; |
199 vp8_info->tl0PicIdx = kNoTl0PicIdx; | 201 vp8_info->tl0PicIdx = kNoTl0PicIdx; |
200 } else { | 202 } else { |
203 RTC_DCHECK_NE(-1, active_layer_); | |
201 vp8_info->temporalIdx = active_layer_; | 204 vp8_info->temporalIdx = active_layer_; |
202 if (base_layer_sync) { | 205 if (base_layer_sync) { |
203 vp8_info->temporalIdx = 0; | 206 vp8_info->temporalIdx = 0; |
204 last_sync_timestamp_ = unwrapped_timestamp; | 207 last_sync_timestamp_ = unwrapped_timestamp; |
205 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { | 208 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { |
206 // Regardless of pattern the frame after a base layer sync will always | 209 // Regardless of pattern the frame after a base layer sync will always |
207 // be a layer sync. | 210 // be a layer sync. |
208 last_sync_timestamp_ = unwrapped_timestamp; | 211 last_sync_timestamp_ = unwrapped_timestamp; |
209 } | 212 } |
210 vp8_info->layerSync = last_sync_timestamp_ != -1 && | 213 vp8_info->layerSync = last_sync_timestamp_ != -1 && |
211 last_sync_timestamp_ == unwrapped_timestamp; | 214 last_sync_timestamp_ == unwrapped_timestamp; |
212 if (vp8_info->temporalIdx == 0) { | 215 if (vp8_info->temporalIdx == 0) { |
213 tl0_pic_idx_++; | 216 tl0_pic_idx_++; |
214 } | 217 } |
215 last_base_layer_sync_ = base_layer_sync; | 218 last_base_layer_sync_ = base_layer_sync; |
216 vp8_info->tl0PicIdx = tl0_pic_idx_; | 219 vp8_info->tl0PicIdx = tl0_pic_idx_; |
217 } | 220 } |
218 } | 221 } |
219 | 222 |
220 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { | 223 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { |
221 if (active_layer_ != 1) { | 224 if (active_layer_ != 1) { |
pbos-webrtc
2016/02/02 21:16:14
Can you DCHECK_NE here as well?
sprang
2016/02/03 10:05:37
Done.
| |
222 RTC_NOTREACHED(); | 225 RTC_NOTREACHED(); |
223 return false; | 226 return false; |
224 } | 227 } |
225 RTC_DCHECK_NE(-1, layers_[0].last_qp); | 228 RTC_DCHECK_NE(-1, layers_[0].last_qp); |
226 if (layers_[1].last_qp == -1) { | 229 if (layers_[1].last_qp == -1) { |
227 // First frame in TL1 should only depend on TL0 since there are no | 230 // First frame in TL1 should only depend on TL0 since there are no |
228 // previous frames in TL1. | 231 // previous frames in TL1. |
229 return true; | 232 return true; |
230 } | 233 } |
231 | 234 |
232 RTC_DCHECK_NE(-1, last_sync_timestamp_); | 235 RTC_DCHECK_NE(-1, last_sync_timestamp_); |
233 int64_t timestamp_diff = timestamp - last_sync_timestamp_; | 236 int64_t timestamp_diff = timestamp - last_sync_timestamp_; |
234 if (timestamp_diff > kMaxTimeBetweenSyncs) { | 237 if (timestamp_diff > kMaxTimeBetweenSyncs) { |
235 // After a certain time, force a sync frame. | 238 // After a certain time, force a sync frame. |
236 return true; | 239 return true; |
237 } else if (timestamp_diff < kMinTimeBetweenSyncs) { | 240 } else if (timestamp_diff < kMinTimeBetweenSyncs) { |
238 // If too soon from previous sync frame, don't issue a new one. | 241 // If too soon from previous sync frame, don't issue a new one. |
239 return false; | 242 return false; |
240 } | 243 } |
241 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too | 244 // Issue a sync frame if difference in quality between TL0 and TL1 isn't too |
242 // large. | 245 // large. |
243 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) | 246 if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync) |
244 return true; | 247 return true; |
245 return false; | 248 return false; |
246 } | 249 } |
247 | 250 |
248 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { | 251 bool ScreenshareLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) { |
249 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) | 252 if (max_qp_ == -1 || number_of_temporal_layers_ <= 1) |
250 return false; | 253 return false; |
254 RTC_DCHECK_NE(-1, active_layer_); | |
251 | 255 |
252 // If layer is in the quality boost state (following a dropped frame), update | 256 // If layer is in the quality boost state (following a dropped frame), update |
253 // the configuration with the adjusted (lower) qp and set the state back to | 257 // the configuration with the adjusted (lower) qp and set the state back to |
254 // normal. | 258 // normal. |
255 unsigned int adjusted_max_qp; | 259 unsigned int adjusted_max_qp; |
256 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && | 260 if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost && |
257 layers_[active_layer_].enhanced_max_qp != -1) { | 261 layers_[active_layer_].enhanced_max_qp != -1) { |
258 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; | 262 adjusted_max_qp = layers_[active_layer_].enhanced_max_qp; |
259 layers_[active_layer_].state = TemporalLayer::State::kNormal; | 263 layers_[active_layer_].state = TemporalLayer::State::kNormal; |
260 } else { | 264 } else { |
(...skipping 12 matching lines...) Expand all Loading... | |
273 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { | 277 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { |
274 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; | 278 uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8; |
275 if (debt_reduction_bytes >= debt_bytes_) { | 279 if (debt_reduction_bytes >= debt_bytes_) { |
276 debt_bytes_ = 0; | 280 debt_bytes_ = 0; |
277 } else { | 281 } else { |
278 debt_bytes_ -= debt_reduction_bytes; | 282 debt_bytes_ -= debt_reduction_bytes; |
279 } | 283 } |
280 } | 284 } |
281 | 285 |
282 } // namespace webrtc | 286 } // namespace webrtc |
OLD | NEW |