| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale. | 71 encode_framerate_(1000.0f, 1000.0f), // 1 second window, second scale. |
| 72 bitrate_updated_(false) { | 72 bitrate_updated_(false) { |
| 73 RTC_CHECK_GT(number_of_temporal_layers_, 0); | 73 RTC_CHECK_GT(number_of_temporal_layers_, 0); |
| 74 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers); | 74 RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers); |
| 75 } | 75 } |
| 76 | 76 |
| 77 ScreenshareLayers::~ScreenshareLayers() { | 77 ScreenshareLayers::~ScreenshareLayers() { |
| 78 UpdateHistograms(); | 78 UpdateHistograms(); |
| 79 } | 79 } |
| 80 | 80 |
| 81 int ScreenshareLayers::CurrentLayerId() const { | 81 int ScreenshareLayers::GetTemporalLayerId( |
| 82 const TemporalLayers::FrameConfig& tl_config) const { |
| 82 // Codec does not use temporal layers for screenshare. | 83 // Codec does not use temporal layers for screenshare. |
| 83 return 0; | 84 return 0; |
| 84 } | 85 } |
| 85 | 86 |
| 86 uint8_t ScreenshareLayers::Tl0PicIdx() const { | 87 uint8_t ScreenshareLayers::Tl0PicIdx() const { |
| 87 return tl0_pic_idx_; | 88 return tl0_pic_idx_; |
| 88 } | 89 } |
| 89 | 90 |
| 90 TemporalReferences ScreenshareLayers::UpdateLayerConfig(uint32_t timestamp) { | 91 TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig( |
| 92 uint32_t timestamp) { |
| 91 if (number_of_temporal_layers_ <= 1) { | 93 if (number_of_temporal_layers_ <= 1) { |
| 92 // No flags needed for 1 layer screenshare. | 94 // No flags needed for 1 layer screenshare. |
| 93 // TODO(pbos): Consider updating only last, and not all buffers. | 95 // TODO(pbos): Consider updating only last, and not all buffers. |
| 94 return TemporalReferences(kReferenceAndUpdate, kReferenceAndUpdate, | 96 return TemporalLayers::FrameConfig(kReferenceAndUpdate, kReferenceAndUpdate, |
| 95 kReferenceAndUpdate); | 97 kReferenceAndUpdate); |
| 96 } | 98 } |
| 97 | 99 |
| 98 const int64_t now_ms = clock_->TimeInMilliseconds(); | 100 const int64_t now_ms = clock_->TimeInMilliseconds(); |
| 99 if (target_framerate_.value_or(0) > 0 && | 101 if (target_framerate_.value_or(0) > 0 && |
| 100 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) { | 102 encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_) { |
| 101 // Max framerate exceeded, drop frame. | 103 // Max framerate exceeded, drop frame. |
| 102 return TemporalReferences(kNone, kNone, kNone); | 104 return TemporalLayers::FrameConfig(kNone, kNone, kNone); |
| 103 } | 105 } |
| 104 | 106 |
| 105 if (stats_.first_frame_time_ms_ == -1) | 107 if (stats_.first_frame_time_ms_ == -1) |
| 106 stats_.first_frame_time_ms_ = now_ms; | 108 stats_.first_frame_time_ms_ = now_ms; |
| 107 | 109 |
| 108 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); | 110 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
| 109 enum TemporalLayerState { kDrop, kTl0, kTl1, kTl1Sync }; | 111 enum TemporalLayerState { kDrop, kTl0, kTl1, kTl1Sync }; |
| 110 enum TemporalLayerState layer_state = kDrop; | 112 enum TemporalLayerState layer_state = kDrop; |
| 111 if (active_layer_ == -1 || | 113 if (active_layer_ == -1 || |
| 112 layers_[active_layer_].state != TemporalLayer::State::kDropped) { | 114 layers_[active_layer_].state != TemporalLayer::State::kDropped) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 ts_diff = unwrapped_timestamp - last_timestamp_; | 160 ts_diff = unwrapped_timestamp - last_timestamp_; |
| 159 } | 161 } |
| 160 // Make sure both frame droppers leak out bits. | 162 // Make sure both frame droppers leak out bits. |
| 161 layers_[0].UpdateDebt(ts_diff / 90); | 163 layers_[0].UpdateDebt(ts_diff / 90); |
| 162 layers_[1].UpdateDebt(ts_diff / 90); | 164 layers_[1].UpdateDebt(ts_diff / 90); |
| 163 last_timestamp_ = timestamp; | 165 last_timestamp_ = timestamp; |
| 164 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all | 166 // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all |
| 165 // layers. | 167 // layers. |
| 166 switch (layer_state) { | 168 switch (layer_state) { |
| 167 case kDrop: | 169 case kDrop: |
| 168 return TemporalReferences(kNone, kNone, kNone); | 170 return TemporalLayers::FrameConfig(kNone, kNone, kNone); |
| 169 case kTl0: | 171 case kTl0: |
| 170 // TL0 only references and updates 'last'. | 172 // TL0 only references and updates 'last'. |
| 171 return TemporalReferences(kReferenceAndUpdate, kNone, kNone); | 173 return TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone); |
| 172 case kTl1: | 174 case kTl1: |
| 173 // TL1 references both 'last' and 'golden' but only updates 'golden'. | 175 // TL1 references both 'last' and 'golden' but only updates 'golden'. |
| 174 return TemporalReferences(kReference, kReferenceAndUpdate, kNone); | 176 return TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, |
| 177 kNone); |
| 175 case kTl1Sync: | 178 case kTl1Sync: |
| 176 // Predict from only TL0 to allow participants to switch to the high | 179 // Predict from only TL0 to allow participants to switch to the high |
| 177 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to | 180 // bitrate stream. Updates 'golden' so that TL1 can continue to refer to |
| 178 // and update 'golden' from this point on. | 181 // and update 'golden' from this point on. |
| 179 return TemporalReferences(kReference, kUpdate, kNone, kLayerSync); | 182 return TemporalLayers::FrameConfig(kReference, kUpdate, kNone, |
| 183 kLayerSync); |
| 180 } | 184 } |
| 181 RTC_NOTREACHED(); | 185 RTC_NOTREACHED(); |
| 182 return TemporalReferences(kNone, kNone, kNone); | 186 return TemporalLayers::FrameConfig(kNone, kNone, kNone); |
| 183 } | 187 } |
| 184 | 188 |
| 185 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, | 189 std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps, |
| 186 int max_bitrate_kbps, | 190 int max_bitrate_kbps, |
| 187 int framerate) { | 191 int framerate) { |
| 188 RTC_DCHECK_GT(framerate, 0); | 192 RTC_DCHECK_GT(framerate, 0); |
| 189 if (!target_framerate_) { | 193 if (!target_framerate_) { |
| 190 // First OnRatesUpdated() is called during construction, with the configured | 194 // First OnRatesUpdated() is called during construction, with the configured |
| 191 // targets as parameters. | 195 // targets as parameters. |
| 192 target_framerate_.emplace(framerate); | 196 target_framerate_.emplace(framerate); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_; | 247 stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_; |
| 244 stats_.tl0_qp_sum_ += qp; | 248 stats_.tl0_qp_sum_ += qp; |
| 245 } else if (active_layer_ == 1) { | 249 } else if (active_layer_ == 1) { |
| 246 layers_[1].debt_bytes_ += size; | 250 layers_[1].debt_bytes_ += size; |
| 247 ++stats_.num_tl1_frames_; | 251 ++stats_.num_tl1_frames_; |
| 248 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_; | 252 stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_; |
| 249 stats_.tl1_qp_sum_ += qp; | 253 stats_.tl1_qp_sum_ += qp; |
| 250 } | 254 } |
| 251 } | 255 } |
| 252 | 256 |
| 253 void ScreenshareLayers::PopulateCodecSpecific(bool frame_is_keyframe, | 257 void ScreenshareLayers::PopulateCodecSpecific( |
| 254 CodecSpecificInfoVP8* vp8_info, | 258 bool frame_is_keyframe, |
| 255 uint32_t timestamp) { | 259 const TemporalLayers::FrameConfig& tl_config, |
| 260 CodecSpecificInfoVP8* vp8_info, |
| 261 uint32_t timestamp) { |
| 256 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); | 262 int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
| 257 if (number_of_temporal_layers_ == 1) { | 263 if (number_of_temporal_layers_ == 1) { |
| 258 vp8_info->temporalIdx = kNoTemporalIdx; | 264 vp8_info->temporalIdx = kNoTemporalIdx; |
| 259 vp8_info->layerSync = false; | 265 vp8_info->layerSync = false; |
| 260 vp8_info->tl0PicIdx = kNoTl0PicIdx; | 266 vp8_info->tl0PicIdx = kNoTl0PicIdx; |
| 261 } else { | 267 } else { |
| 268 // TODO(pbos): Add active_layer_ to TemporalLayers::FrameConfig (as |
| 269 // pattern_idx) and make function const. |
| 262 RTC_DCHECK_NE(-1, active_layer_); | 270 RTC_DCHECK_NE(-1, active_layer_); |
| 263 vp8_info->temporalIdx = active_layer_; | 271 vp8_info->temporalIdx = active_layer_; |
| 264 if (frame_is_keyframe) { | 272 if (frame_is_keyframe) { |
| 265 vp8_info->temporalIdx = 0; | 273 vp8_info->temporalIdx = 0; |
| 266 last_sync_timestamp_ = unwrapped_timestamp; | 274 last_sync_timestamp_ = unwrapped_timestamp; |
| 267 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { | 275 } else if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { |
| 268 // Regardless of pattern the frame after a base layer sync will always | 276 // Regardless of pattern the frame after a base layer sync will always |
| 269 // be a layer sync. | 277 // be a layer sync. |
| 270 last_sync_timestamp_ = unwrapped_timestamp; | 278 last_sync_timestamp_ = unwrapped_timestamp; |
| 271 } | 279 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", | 429 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp", |
| 422 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); | 430 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_); |
| 423 RTC_HISTOGRAM_COUNTS_10000( | 431 RTC_HISTOGRAM_COUNTS_10000( |
| 424 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", | 432 "WebRTC.Video.Screenshare.Layer1.TargetBitrate", |
| 425 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); | 433 stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_); |
| 426 } | 434 } |
| 427 } | 435 } |
| 428 } | 436 } |
| 429 | 437 |
| 430 } // namespace webrtc | 438 } // namespace webrtc |
| OLD | NEW |