Chromium Code Reviews| 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 |