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 14 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |