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

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

Issue 2769263002: Base screenshare layers on TemporalReferences. (Closed)
Patch Set: feedback Created 3 years, 8 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
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 14 matching lines...) Expand all
25 static const int kOneSecond90Khz = 90000; 25 static const int kOneSecond90Khz = 90000;
26 static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 5; 26 static const int kMinTimeBetweenSyncs = kOneSecond90Khz * 5;
27 static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 10; 27 static const int kMaxTimeBetweenSyncs = kOneSecond90Khz * 10;
28 static const int kQpDeltaThresholdForSync = 8; 28 static const int kQpDeltaThresholdForSync = 8;
29 29
30 const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5; 30 const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
31 const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0; 31 const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
32 32
33 constexpr int ScreenshareLayers::kMaxNumTemporalLayers; 33 constexpr int ScreenshareLayers::kMaxNumTemporalLayers;
34 34
35 // Since this is TL0 we only allow updating and predicting from the LAST
36 // reference frame.
37 const int ScreenshareLayers::kTl0Flags =
38 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF |
39 VP8_EFLAG_NO_REF_ARF;
40
41 // Allow predicting from both TL0 and TL1.
42 const int ScreenshareLayers::kTl1Flags =
43 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
44
45 // Allow predicting from only TL0 to allow participants to switch to the high
46 // bitrate stream. This means predicting only from the LAST reference frame, but
47 // only updating GF to not corrupt TL0.
48 const int ScreenshareLayers::kTl1SyncFlags =
49 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
50 VP8_EFLAG_NO_UPD_LAST;
51
52 // Always emit a frame with certain interval, even if bitrate targets have 35 // Always emit a frame with certain interval, even if bitrate targets have
53 // been exceeded. 36 // been exceeded.
54 const int ScreenshareLayers::kMaxFrameIntervalMs = 2000; 37 const int ScreenshareLayers::kMaxFrameIntervalMs = 2000;
55 38
56 webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create( 39 webrtc::TemporalLayers* ScreenshareTemporalLayersFactory::Create(
57 int simulcast_id, 40 int simulcast_id,
58 int num_temporal_layers, 41 int num_temporal_layers,
59 uint8_t initial_tl0_pic_idx) const { 42 uint8_t initial_tl0_pic_idx) const {
60 webrtc::TemporalLayers* tl; 43 webrtc::TemporalLayers* tl;
61 if (simulcast_id == 0) { 44 if (simulcast_id == 0) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 76
94 ScreenshareLayers::~ScreenshareLayers() { 77 ScreenshareLayers::~ScreenshareLayers() {
95 UpdateHistograms(); 78 UpdateHistograms();
96 } 79 }
97 80
98 int ScreenshareLayers::CurrentLayerId() const { 81 int ScreenshareLayers::CurrentLayerId() const {
99 // Codec does not use temporal layers for screenshare. 82 // Codec does not use temporal layers for screenshare.
100 return 0; 83 return 0;
101 } 84 }
102 85
103 int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { 86 TemporalReferences ScreenshareLayers::UpdateLayerConfig(uint32_t timestamp) {
104 if (number_of_temporal_layers_ <= 1) { 87 if (number_of_temporal_layers_ <= 1) {
105 // No flags needed for 1 layer screenshare. 88 // No flags needed for 1 layer screenshare.
106 return 0; 89 // TODO(pbos): Consider updating only last, and not all buffers.
90 return TemporalReferences(kReferenceAndUpdate, kReferenceAndUpdate,
91 kReferenceAndUpdate);
107 } 92 }
108 93
109 const int64_t now_ms = clock_->TimeInMilliseconds(); 94 const int64_t now_ms = clock_->TimeInMilliseconds();
110 if (target_framerate_.value_or(0) > 0 && 95 if (target_framerate_.value_or(0) > 0 &&
111 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) { 96 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) {
112 // Max framerate exceeded, drop frame. 97 // Max framerate exceeded, drop frame.
113 return -1; 98 return TemporalReferences(kNone, kNone, kNone);
114 } 99 }
115 100
116 if (stats_.first_frame_time_ms_ == -1) 101 if (stats_.first_frame_time_ms_ == -1)
117 stats_.first_frame_time_ms_ = now_ms; 102 stats_.first_frame_time_ms_ = now_ms;
118 103
119 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); 104 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
120 int flags = 0; 105 enum TemporalLayerState { kDrop, kTl0, kTl1, kTl1Sync };
106 enum TemporalLayerState layer_state = kDrop;
121 if (active_layer_ == -1 || 107 if (active_layer_ == -1 ||
122 layers_[active_layer_].state != TemporalLayer::State::kDropped) { 108 layers_[active_layer_].state != TemporalLayer::State::kDropped) {
123 if (last_emitted_tl0_timestamp_ != -1 && 109 if (last_emitted_tl0_timestamp_ != -1 &&
124 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 > 110 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
125 kMaxFrameIntervalMs) { 111 kMaxFrameIntervalMs) {
126 // Too long time has passed since the last frame was emitted, cancel 112 // Too long time has passed since the last frame was emitted, cancel
127 // enough debt to allow a single frame. 113 // enough debt to allow a single frame.
128 layers_[0].debt_bytes_ = max_debt_bytes_ - 1; 114 layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
129 } 115 }
130 if (layers_[0].debt_bytes_ > max_debt_bytes_) { 116 if (layers_[0].debt_bytes_ > max_debt_bytes_) {
131 // Must drop TL0, encode TL1 instead. 117 // Must drop TL0, encode TL1 instead.
132 if (layers_[1].debt_bytes_ > max_debt_bytes_) { 118 if (layers_[1].debt_bytes_ > max_debt_bytes_) {
133 // Must drop both TL0 and TL1. 119 // Must drop both TL0 and TL1.
134 active_layer_ = -1; 120 active_layer_ = -1;
135 } else { 121 } else {
136 active_layer_ = 1; 122 active_layer_ = 1;
137 } 123 }
138 } else { 124 } else {
139 active_layer_ = 0; 125 active_layer_ = 0;
140 } 126 }
141 } 127 }
142 128
143 switch (active_layer_) { 129 switch (active_layer_) {
144 case 0: 130 case 0:
145 flags = kTl0Flags; 131 layer_state = kTl0;
146 last_emitted_tl0_timestamp_ = unwrapped_timestamp; 132 last_emitted_tl0_timestamp_ = unwrapped_timestamp;
147 break; 133 break;
148 case 1: 134 case 1:
149 if (TimeToSync(unwrapped_timestamp)) { 135 if (TimeToSync(unwrapped_timestamp)) {
150 last_sync_timestamp_ = unwrapped_timestamp; 136 last_sync_timestamp_ = unwrapped_timestamp;
151 flags = kTl1SyncFlags; 137 layer_state = kTl1Sync;
152 } else { 138 } else {
153 flags = kTl1Flags; 139 layer_state = kTl1;
154 } 140 }
155 break; 141 break;
156 case -1: 142 case -1:
157 flags = -1; 143 layer_state = kDrop;
158 ++stats_.num_dropped_frames_; 144 ++stats_.num_dropped_frames_;
159 break; 145 break;
160 default: 146 default:
161 flags = -1;
162 RTC_NOTREACHED(); 147 RTC_NOTREACHED();
163 } 148 }
164 149
165 int64_t ts_diff; 150 int64_t ts_diff;
166 if (last_timestamp_ == -1) { 151 if (last_timestamp_ == -1) {
167 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_); 152 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
168 } else { 153 } else {
169 ts_diff = unwrapped_timestamp - last_timestamp_; 154 ts_diff = unwrapped_timestamp - last_timestamp_;
170 } 155 }
171 // Make sure both frame droppers leak out bits. 156 // Make sure both frame droppers leak out bits.
172 layers_[0].UpdateDebt(ts_diff / 90); 157 layers_[0].UpdateDebt(ts_diff / 90);
173 layers_[1].UpdateDebt(ts_diff / 90); 158 layers_[1].UpdateDebt(ts_diff / 90);
174 last_timestamp_ = timestamp; 159 last_timestamp_ = timestamp;
175 return flags; 160 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
161 // layers.
162 switch (layer_state) {
163 case kDrop:
164 return TemporalReferences(kNone, kNone, kNone);
165 case kTl0:
166 // TL0 only references and updates 'last'.
167 return TemporalReferences(kReferenceAndUpdate, kNone, kNone);
168 case kTl1:
169 // TL1 references both 'last' and 'golden' but only updates 'golden'.
170 return TemporalReferences(kReference, kReferenceAndUpdate, kNone);
171 case kTl1Sync:
172 // Predict from only TL0 to allow participants to switch to the high
173 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
174 // and update 'golden' from this point on.
175 return TemporalReferences(kReference, kUpdate, kNone, kLayerSync);
176 }
177 RTC_NOTREACHED();
178 return TemporalReferences(kNone, kNone, kNone);
176 } 179 }
177 180
178 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, 181 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps,
179 int max_bitrate_kbps, 182 int max_bitrate_kbps,
180 int framerate) { 183 int framerate) {
181 RTC_DCHECK_GT(framerate, 0); 184 RTC_DCHECK_GT(framerate, 0);
182 if (!target_framerate_) { 185 if (!target_framerate_) {
183 // First OnRatesUpdated() is called during construction, with the configured 186 // First OnRatesUpdated() is called during construction, with the configured
184 // targets as parameters. 187 // targets as parameters.
185 target_framerate_.emplace(framerate); 188 target_framerate_.emplace(framerate);
(...skipping 15 matching lines...) Expand all
201 layers_[0].target_rate_kbps_ = bitrate_kbps; 204 layers_[0].target_rate_kbps_ = bitrate_kbps;
202 layers_[1].target_rate_kbps_ = max_bitrate_kbps; 205 layers_[1].target_rate_kbps_ = max_bitrate_kbps;
203 206
204 std::vector<uint32_t> allocation; 207 std::vector<uint32_t> allocation;
205 allocation.push_back(bitrate_kbps); 208 allocation.push_back(bitrate_kbps);
206 if (max_bitrate_kbps > bitrate_kbps) 209 if (max_bitrate_kbps > bitrate_kbps)
207 allocation.push_back(max_bitrate_kbps - bitrate_kbps); 210 allocation.push_back(max_bitrate_kbps - bitrate_kbps);
208 return allocation; 211 return allocation;
209 } 212 }
210 213
211 void ScreenshareLayers::FrameEncoded(unsigned int size, 214 void ScreenshareLayers::FrameEncoded(unsigned int size, int qp) {
212 uint32_t timestamp,
213 int qp) {
214 if (size > 0) 215 if (size > 0)
215 encode_framerate_.Update(1, clock_->TimeInMilliseconds()); 216 encode_framerate_.Update(1, clock_->TimeInMilliseconds());
216 217
217 if (number_of_temporal_layers_ == 1) 218 if (number_of_temporal_layers_ == 1)
218 return; 219 return;
219 220
220 RTC_DCHECK_NE(-1, active_layer_); 221 RTC_DCHECK_NE(-1, active_layer_);
221 if (size == 0) { 222 if (size == 0) {
222 layers_[active_layer_].state = TemporalLayer::State::kDropped; 223 layers_[active_layer_].state = TemporalLayer::State::kDropped;
223 ++stats_.num_overshoots_; 224 ++stats_.num_overshoots_;
(...skipping 14 matching lines...) Expand all
238 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_; 239 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
239 stats_.tl0_qp_sum_ += qp; 240 stats_.tl0_qp_sum_ += qp;
240 } else if (active_layer_ == 1) { 241 } else if (active_layer_ == 1) {
241 layers_[1].debt_bytes_ += size; 242 layers_[1].debt_bytes_ += size;
242 ++stats_.num_tl1_frames_; 243 ++stats_.num_tl1_frames_;
243 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_; 244 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
244 stats_.tl1_qp_sum_ += qp; 245 stats_.tl1_qp_sum_ += qp;
245 } 246 }
246 } 247 }
247 248
248 void ScreenshareLayers::PopulateCodecSpecific(bool base_layer_sync, 249 void ScreenshareLayers::PopulateCodecSpecific(bool frame_is_keyframe,
249 CodecSpecificInfoVP8* vp8_info, 250 CodecSpecificInfoVP8* vp8_info,
250 uint32_t timestamp) { 251 uint32_t timestamp) {
251 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); 252 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
252 if (number_of_temporal_layers_ == 1) { 253 if (number_of_temporal_layers_ == 1) {
253 vp8_info->temporalIdx = kNoTemporalIdx; 254 vp8_info->temporalIdx = kNoTemporalIdx;
254 vp8_info->layerSync = false; 255 vp8_info->layerSync = false;
255 vp8_info->tl0PicIdx = kNoTl0PicIdx; 256 vp8_info->tl0PicIdx = kNoTl0PicIdx;
256 } else { 257 } else {
257 RTC_DCHECK_NE(-1, active_layer_); 258 RTC_DCHECK_NE(-1, active_layer_);
258 vp8_info->temporalIdx = active_layer_; 259 vp8_info->temporalIdx = active_layer_;
259 if (base_layer_sync) { 260 if (frame_is_keyframe) {
260 vp8_info->temporalIdx = 0; 261 vp8_info->temporalIdx = 0;
261 last_sync_timestamp_ = unwrapped_timestamp; 262 last_sync_timestamp_ = unwrapped_timestamp;
262 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { 263 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
263 // Regardless of pattern the frame after a base layer sync will always 264 // Regardless of pattern the frame after a base layer sync will always
264 // be a layer sync. 265 // be a layer sync.
265 last_sync_timestamp_ = unwrapped_timestamp; 266 last_sync_timestamp_ = unwrapped_timestamp;
266 } 267 }
267 vp8_info->layerSync = last_sync_timestamp_ != -1 && 268 vp8_info->layerSync = last_sync_timestamp_ != -1 &&
268 last_sync_timestamp_ == unwrapped_timestamp; 269 last_sync_timestamp_ == unwrapped_timestamp;
269 if (vp8_info->temporalIdx == 0) { 270 if (vp8_info->temporalIdx == 0) {
270 tl0_pic_idx_++; 271 tl0_pic_idx_++;
271 } 272 }
272 last_base_layer_sync_ = base_layer_sync; 273 last_base_layer_sync_ = frame_is_keyframe;
273 vp8_info->tl0PicIdx = tl0_pic_idx_; 274 vp8_info->tl0PicIdx = tl0_pic_idx_;
274 } 275 }
275 } 276 }
276 277
277 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { 278 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
278 RTC_DCHECK_EQ(1, active_layer_); 279 RTC_DCHECK_EQ(1, active_layer_);
279 RTC_DCHECK_NE(-1, layers_[0].last_qp); 280 RTC_DCHECK_NE(-1, layers_[0].last_qp);
280 if (layers_[1].last_qp == -1) { 281 if (layers_[1].last_qp == -1) {
281 // First frame in TL1 should only depend on TL0 since there are no 282 // First frame in TL1 should only depend on TL0 since there are no
282 // previous frames in TL1. 283 // previous frames in TL1.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", 417 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
417 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); 418 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
418 RTC_HISTOGRAM_COUNTS_10000( 419 RTC_HISTOGRAM_COUNTS_10000(
419 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", 420 "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
420 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); 421 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
421 } 422 }
422 } 423 }
423 } 424 }
424 425
425 } // namespace webrtc 426 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698