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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale. | 72 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale. |
| 73 bitrate_updated_(false) { | 73 bitrate_updated_(false) { |
| 74 RTC_CHECK_GT(number_of_temporal_layers_, 0); | 74 RTC_CHECK_GT(number_of_temporal_layers_, 0); |
| 75 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers); | 75 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers); |
| 76 } | 76 } |
| 77 | 77 |
| 78 ScreenshareLayers::~ScreenshareLayers() { | 78 ScreenshareLayers::~ScreenshareLayers() { |
| 79 UpdateHistograms(); | 79 UpdateHistograms(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 int ScreenshareLayers::GetTemporalLayerId( | |
| 83 const TemporalLayers::FrameConfig& tl_config) const { | |
| 84 // Codec does not use temporal layers for screenshare. | |
| 85 return 0; | |
| 86 } | |
| 87 | |
| 88 uint8_t ScreenshareLayers::Tl0PicIdx() const { | 82 uint8_t ScreenshareLayers::Tl0PicIdx() const { |
| 89 return tl0_pic_idx_; | 83 return tl0_pic_idx_; |
| 90 } | 84 } |
| 91 | 85 |
| 92 TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig( | 86 TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig( |
| 93 uint32_t timestamp) { | 87 uint32_t timestamp) { |
| 94 if (number_of_temporal_layers_ <= 1) { | 88 if (number_of_temporal_layers_ <= 1) { |
| 95 // No flags needed for 1 layer screenshare. | 89 // No flags needed for 1 layer screenshare. |
| 96 // TODO(pbos): Consider updating only last, and not all buffers. | 90 // TODO(pbos): Consider updating only last, and not all buffers. |
| 97 TemporalLayers::FrameConfig tl_config( | 91 TemporalLayers::FrameConfig tl_config( |
| 98 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate); | 92 kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate); |
| 99 tl_config.pattern_idx = static_cast<int>(TemporalLayerState::kTl1); | |
| 100 return tl_config; | 93 return tl_config; |
| 101 } | 94 } |
| 102 | 95 |
| 103 const int64_t now_ms = clock_->TimeInMilliseconds(); | 96 const int64_t now_ms = clock_->TimeInMilliseconds(); |
| 104 if (target_framerate_.value_or(0) > 0 && | 97 if (target_framerate_.value_or(0) > 0 && |
| 105 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) { | 98 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) { |
| 106 // Max framerate exceeded, drop frame. | 99 // Max framerate exceeded, drop frame. |
| 107 return TemporalLayers::FrameConfig(kNone, kNone, kNone); | 100 return TemporalLayers::FrameConfig(kNone, kNone, kNone); |
| 108 } | 101 } |
| 109 | 102 |
| 110 if (stats_.first_frame_time_ms_ == -1) | 103 if (stats_.first_frame_time_ms_ == -1) |
| 111 stats_.first_frame_time_ms_ = now_ms; | 104 stats_.first_frame_time_ms_ = now_ms; |
| 112 | 105 |
| 113 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); | 106 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
| 114 int64_t ts_diff; | 107 int64_t ts_diff; |
| 115 if (last_timestamp_ == -1) { | 108 if (last_timestamp_ == -1) { |
| 116 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_); | 109 ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_); |
| 117 } else { | 110 } else { |
| 118 ts_diff = unwrapped_timestamp - last_timestamp_; | 111 ts_diff = unwrapped_timestamp - last_timestamp_; |
| 119 } | 112 } |
| 120 // Make sure both frame droppers leak out bits. | 113 // Make sure both frame droppers leak out bits. |
| 121 layers_[0].UpdateDebt(ts_diff / 90); | 114 layers_[0].UpdateDebt(ts_diff / 90); |
| 122 layers_[1].UpdateDebt(ts_diff / 90); | 115 layers_[1].UpdateDebt(ts_diff / 90); |
| 123 last_timestamp_ = timestamp; | 116 last_timestamp_ = timestamp; |
| 124 | 117 |
| 125 TemporalLayerState layer_state = TemporalLayerState::kDrop; | 118 TemporalLayerState layer_state = |
| 119 TemporalLayerState::kDrop; | |
|
brandtr
2017/06/12 15:15:53
revert?
pbos-webrtc
2017/06/15 21:59:09
Done.
| |
| 126 | 120 |
| 127 if (active_layer_ == -1 || | 121 if (active_layer_ == -1 || |
| 128 layers_[active_layer_].state != TemporalLayer::State::kDropped) { | 122 layers_[active_layer_].state != TemporalLayer::State::kDropped) { |
| 129 if (last_emitted_tl0_timestamp_ != -1 && | 123 if (last_emitted_tl0_timestamp_ != -1 && |
| 130 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 > | 124 (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 > |
| 131 kMaxFrameIntervalMs) { | 125 kMaxFrameIntervalMs) { |
| 132 // Too long time has passed since the last frame was emitted, cancel | 126 // Too long time has passed since the last frame was emitted, cancel |
| 133 // enough debt to allow a single frame. | 127 // enough debt to allow a single frame. |
| 134 layers_[0].debt_bytes_ = max_debt_bytes_ - 1; | 128 layers_[0].debt_bytes_ = max_debt_bytes_ - 1; |
| 135 } | 129 } |
| 136 if (layers_[0].debt_bytes_ > max_debt_bytes_) { | 130 if (layers_[0].debt_bytes_ > max_debt_bytes_) { |
| 137 // Must drop TL0, encode TL1 instead. | 131 // Must drop TL0, encode TL1 instead. |
| 138 if (layers_[1].debt_bytes_ > max_debt_bytes_) { | 132 if (layers_[1].debt_bytes_ > max_debt_bytes_) { |
| 139 // Must drop both TL0 and TL1. | 133 // Must drop both TL0 and TL1. |
| 140 active_layer_ = -1; | 134 active_layer_ = -1; |
| 141 } else { | 135 } else { |
| 142 active_layer_ = 1; | 136 active_layer_ = 1; |
| 143 } | 137 } |
| 144 } else { | 138 } else { |
| 145 active_layer_ = 0; | 139 active_layer_ = 0; |
| 146 } | 140 } |
| 147 } | 141 } |
| 148 | 142 |
| 143 bool layer_sync = false; | |
| 149 switch (active_layer_) { | 144 switch (active_layer_) { |
| 150 case 0: | 145 case 0: |
| 151 layer_state = TemporalLayerState::kTl0; | 146 layer_state = TemporalLayerState::kTl0; |
| 152 last_emitted_tl0_timestamp_ = unwrapped_timestamp; | 147 last_emitted_tl0_timestamp_ = unwrapped_timestamp; |
| 153 break; | 148 break; |
| 154 case 1: | 149 case 1: |
| 155 if (TimeToSync(unwrapped_timestamp)) { | 150 if (TimeToSync(unwrapped_timestamp)) { |
| 151 layer_sync = true; | |
| 156 last_sync_timestamp_ = unwrapped_timestamp; | 152 last_sync_timestamp_ = unwrapped_timestamp; |
| 157 layer_state = TemporalLayerState::kTl1Sync; | 153 layer_state = TemporalLayerState::kTl1Sync; |
| 158 } else { | 154 } else { |
| 159 layer_state = TemporalLayerState::kTl1; | 155 layer_state = TemporalLayerState::kTl1; |
| 160 } | 156 } |
| 161 break; | 157 break; |
| 162 case -1: | 158 case -1: |
| 163 layer_state = TemporalLayerState::kDrop; | 159 layer_state = TemporalLayerState::kDrop; |
| 164 ++stats_.num_dropped_frames_; | 160 ++stats_.num_dropped_frames_; |
| 165 break; | 161 break; |
| 166 default: | 162 default: |
| 167 RTC_NOTREACHED(); | 163 RTC_NOTREACHED(); |
| 168 } | 164 } |
| 169 | 165 |
| 170 TemporalLayers::FrameConfig tl_config; | 166 TemporalLayers::FrameConfig tl_config; |
| 171 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all | 167 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all |
| 172 // layers. | 168 // layers. |
| 173 switch (layer_state) { | 169 switch (layer_state) { |
| 174 case TemporalLayerState::kDrop: | 170 case TemporalLayerState::kDrop: |
| 175 tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone); | 171 tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone); |
| 176 break; | 172 break; |
| 177 case TemporalLayerState::kTl0: | 173 case TemporalLayerState::kTl0: |
| 178 // TL0 only references and updates 'last'. | 174 // TL0 only references and updates 'last'. |
| 179 tl_config = | 175 tl_config = |
| 180 TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone); | 176 TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone); |
|
brandtr
2017/06/12 15:15:53
Add tl_config.packetizer_temporal_idx = 0; explici
pbos-webrtc
2017/06/15 21:59:09
Done.
| |
| 181 break; | 177 break; |
| 182 case TemporalLayerState::kTl1: | 178 case TemporalLayerState::kTl1: |
| 183 // TL1 references both 'last' and 'golden' but only updates 'golden'. | 179 // TL1 references both 'last' and 'golden' but only updates 'golden'. |
| 184 tl_config = | 180 tl_config = |
| 185 TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone); | 181 TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone); |
| 182 tl_config.packetizer_temporal_idx = 1; | |
| 186 break; | 183 break; |
| 187 case TemporalLayerState::kTl1Sync: | 184 case TemporalLayerState::kTl1Sync: |
| 188 // Predict from only TL0 to allow participants to switch to the high | 185 // Predict from only TL0 to allow participants to switch to the high |
| 189 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to | 186 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to |
| 190 // and update 'golden' from this point on. | 187 // and update 'golden' from this point on. |
| 191 tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone); | 188 tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone); |
| 189 tl_config.packetizer_temporal_idx = 1; | |
| 192 break; | 190 break; |
| 193 } | 191 } |
| 194 | 192 |
| 195 tl_config.pattern_idx = static_cast<int>(layer_state); | 193 tl_config.layer_sync = layer_sync; |
| 196 return tl_config; | 194 return tl_config; |
| 197 } | 195 } |
| 198 | 196 |
| 199 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, | 197 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, |
| 200 int max_bitrate_kbps, | 198 int max_bitrate_kbps, |
| 201 int framerate) { | 199 int framerate) { |
| 202 RTC_DCHECK_GT(framerate, 0); | 200 RTC_DCHECK_GT(framerate, 0); |
| 203 if (!target_framerate_) { | 201 if (!target_framerate_) { |
| 204 // First OnRatesUpdated() is called during construction, with the configured | 202 // First OnRatesUpdated() is called during construction, with the configured |
| 205 // targets as parameters. | 203 // targets as parameters. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_; | 260 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_; |
| 263 stats_.tl1_qp_sum_ += qp; | 261 stats_.tl1_qp_sum_ += qp; |
| 264 } | 262 } |
| 265 } | 263 } |
| 266 | 264 |
| 267 void ScreenshareLayers::PopulateCodecSpecific( | 265 void ScreenshareLayers::PopulateCodecSpecific( |
| 268 bool frame_is_keyframe, | 266 bool frame_is_keyframe, |
| 269 const TemporalLayers::FrameConfig& tl_config, | 267 const TemporalLayers::FrameConfig& tl_config, |
| 270 CodecSpecificInfoVP8* vp8_info, | 268 CodecSpecificInfoVP8* vp8_info, |
| 271 uint32_t timestamp) { | 269 uint32_t timestamp) { |
| 272 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); | |
| 273 if (number_of_temporal_layers_ == 1) { | 270 if (number_of_temporal_layers_ == 1) { |
| 274 vp8_info->temporalIdx = kNoTemporalIdx; | 271 vp8_info->temporalIdx = kNoTemporalIdx; |
| 275 vp8_info->layerSync = false; | 272 vp8_info->layerSync = false; |
| 276 vp8_info->tl0PicIdx = kNoTl0PicIdx; | 273 vp8_info->tl0PicIdx = kNoTl0PicIdx; |
| 277 } else { | 274 } else { |
| 278 TemporalLayerState layer_state = | 275 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
| 279 static_cast<TemporalLayerState>(tl_config.pattern_idx); | 276 vp8_info->temporalIdx = tl_config.packetizer_temporal_idx; |
| 280 switch (layer_state) { | 277 vp8_info->layerSync = tl_config.layer_sync; |
| 281 case TemporalLayerState::kDrop: | |
| 282 RTC_NOTREACHED(); | |
| 283 break; | |
| 284 case TemporalLayerState::kTl0: | |
| 285 vp8_info->temporalIdx = 0; | |
| 286 break; | |
| 287 case TemporalLayerState::kTl1: | |
| 288 case TemporalLayerState::kTl1Sync: | |
| 289 vp8_info->temporalIdx = 1; | |
| 290 break; | |
| 291 } | |
| 292 if (frame_is_keyframe) { | 278 if (frame_is_keyframe) { |
| 293 vp8_info->temporalIdx = 0; | 279 vp8_info->temporalIdx = 0; |
| 294 last_sync_timestamp_ = unwrapped_timestamp; | 280 last_sync_timestamp_ = unwrapped_timestamp; |
| 281 vp8_info->layerSync = true; | |
| 295 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { | 282 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { |
| 296 // Regardless of pattern the frame after a base layer sync will always | 283 // Regardless of pattern the frame after a base layer sync will always |
| 297 // be a layer sync. | 284 // be a layer sync. |
| 298 last_sync_timestamp_ = unwrapped_timestamp; | 285 last_sync_timestamp_ = unwrapped_timestamp; |
| 286 vp8_info->layerSync = true; | |
| 299 } | 287 } |
| 300 vp8_info->layerSync = last_sync_timestamp_ != -1 && | |
| 301 last_sync_timestamp_ == unwrapped_timestamp; | |
| 302 if (vp8_info->temporalIdx == 0) { | 288 if (vp8_info->temporalIdx == 0) { |
| 303 tl0_pic_idx_++; | 289 tl0_pic_idx_++; |
| 304 } | 290 } |
| 305 last_base_layer_sync_ = frame_is_keyframe; | 291 last_base_layer_sync_ = frame_is_keyframe; |
| 306 vp8_info->tl0PicIdx = tl0_pic_idx_; | 292 vp8_info->tl0PicIdx = tl0_pic_idx_; |
| 307 } | 293 } |
| 308 } | 294 } |
| 309 | 295 |
| 310 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { | 296 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const { |
| 311 RTC_DCHECK_EQ(1, active_layer_); | 297 RTC_DCHECK_EQ(1, active_layer_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", | 446 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", |
| 461 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); | 447 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); |
| 462 RTC_HISTOGRAM_COUNTS_10000( | 448 RTC_HISTOGRAM_COUNTS_10000( |
| 463 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", | 449 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", |
| 464 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); | 450 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); |
| 465 } | 451 } |
| 466 } | 452 } |
| 467 } | 453 } |
| 468 | 454 |
| 469 } // namespace webrtc | 455 } // namespace webrtc |
| OLD | NEW |