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

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: Test error + brain fartin ConfigureBitrates 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 | webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc » ('j') | 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 : number_of_temporal_layers_(num_temporal_layers), 50 : number_of_temporal_layers_(num_temporal_layers),
51 last_base_layer_sync_(false), 51 last_base_layer_sync_(false),
52 tl0_pic_idx_(initial_tl0_pic_idx), 52 tl0_pic_idx_(initial_tl0_pic_idx),
53 active_layer_(-1), 53 active_layer_(-1),
54 last_timestamp_(-1), 54 last_timestamp_(-1),
55 last_sync_timestamp_(-1), 55 last_sync_timestamp_(-1),
56 min_qp_(-1), 56 min_qp_(-1),
57 max_qp_(-1), 57 max_qp_(-1),
58 max_debt_bytes_(0), 58 max_debt_bytes_(0),
59 frame_rate_(-1) { 59 frame_rate_(-1) {
60 assert(num_temporal_layers > 0); 60 RTC_CHECK_GT(num_temporal_layers, 0);
61 assert(num_temporal_layers <= 2); 61 RTC_CHECK_LE(num_temporal_layers, 2);
62 } 62 }
63 63
64 int ScreenshareLayers::CurrentLayerId() const { 64 int ScreenshareLayers::CurrentLayerId() const {
65 // Codec does not use temporal layers for screenshare. 65 // Codec does not use temporal layers for screenshare.
66 return 0; 66 return 0;
67 } 67 }
68 68
69 int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { 69 int ScreenshareLayers::EncodeFlags(uint32_t timestamp) {
70 if (number_of_temporal_layers_ <= 1) { 70 if (number_of_temporal_layers_ <= 1) {
71 // No flags needed for 1 layer screenshare. 71 // No flags needed for 1 layer screenshare.
(...skipping 68 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 ||
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 if (number_of_temporal_layers_ == 1)
174 return;
175
176 RTC_DCHECK_NE(-1, active_layer_);
172 if (size == 0) { 177 if (size == 0) {
173 layers_[active_layer_].state = TemporalLayer::State::kDropped; 178 layers_[active_layer_].state = TemporalLayer::State::kDropped;
174 return; 179 return;
175 } 180 }
176 181
177 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) { 182 if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
178 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost; 183 layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
179 } 184 }
180 185
181 if (qp != -1) 186 if (qp != -1)
182 layers_[active_layer_].last_qp = qp; 187 layers_[active_layer_].last_qp = qp;
183 188
184 if (active_layer_ == 0) { 189 if (active_layer_ == 0) {
185 layers_[0].debt_bytes_ += size; 190 layers_[0].debt_bytes_ += size;
186 layers_[1].debt_bytes_ += size; 191 layers_[1].debt_bytes_ += size;
187 } else if (active_layer_ == 1) { 192 } else if (active_layer_ == 1) {
188 layers_[1].debt_bytes_ += size; 193 layers_[1].debt_bytes_ += size;
189 } 194 }
190 } 195 }
191 196
192 void ScreenshareLayers::PopulateCodecSpecific(bool base_layer_sync, 197 void ScreenshareLayers::PopulateCodecSpecific(bool base_layer_sync,
193 CodecSpecificInfoVP8* vp8_info, 198 CodecSpecificInfoVP8* vp8_info,
194 uint32_t timestamp) { 199 uint32_t timestamp) {
195 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); 200 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
196 if (number_of_temporal_layers_ == 1) { 201 if (number_of_temporal_layers_ == 1) {
197 vp8_info->temporalIdx = kNoTemporalIdx; 202 vp8_info->temporalIdx = kNoTemporalIdx;
198 vp8_info->layerSync = false; 203 vp8_info->layerSync = false;
199 vp8_info->tl0PicIdx = kNoTl0PicIdx; 204 vp8_info->tl0PicIdx = kNoTl0PicIdx;
200 } else { 205 } else {
206 RTC_DCHECK_NE(-1, active_layer_);
201 vp8_info->temporalIdx = active_layer_; 207 vp8_info->temporalIdx = active_layer_;
202 if (base_layer_sync) { 208 if (base_layer_sync) {
203 vp8_info->temporalIdx = 0; 209 vp8_info->temporalIdx = 0;
204 last_sync_timestamp_ = unwrapped_timestamp; 210 last_sync_timestamp_ = unwrapped_timestamp;
205 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { 211 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
206 // Regardless of pattern the frame after a base layer sync will always 212 // Regardless of pattern the frame after a base layer sync will always
207 // be a layer sync. 213 // be a layer sync.
208 last_sync_timestamp_ = unwrapped_timestamp; 214 last_sync_timestamp_ = unwrapped_timestamp;
209 } 215 }
210 vp8_info->layerSync = last_sync_timestamp_ != -1 && 216 vp8_info->layerSync = last_sync_timestamp_ != -1 &&
211 last_sync_timestamp_ == unwrapped_timestamp; 217 last_sync_timestamp_ == unwrapped_timestamp;
212 if (vp8_info->temporalIdx == 0) { 218 if (vp8_info->temporalIdx == 0) {
213 tl0_pic_idx_++; 219 tl0_pic_idx_++;
214 } 220 }
215 last_base_layer_sync_ = base_layer_sync; 221 last_base_layer_sync_ = base_layer_sync;
216 vp8_info->tl0PicIdx = tl0_pic_idx_; 222 vp8_info->tl0PicIdx = tl0_pic_idx_;
217 } 223 }
218 } 224 }
219 225
220 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { 226 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
221 if (active_layer_ != 1) { 227 RTC_DCHECK_EQ(1, active_layer_);
222 RTC_NOTREACHED();
223 return false;
224 }
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 | webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698