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

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

Issue 1656233002: Avoid undefined behavior in vp8 screenshare_layers (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 10 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698