Index: webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc |
diff --git a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc |
index 2b7f7195d54bcf822606ce93848e07ba207095c5..aa75ef1414d92549f4b664a81da870277b11abd5 100644 |
--- a/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc |
+++ b/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc |
@@ -47,6 +47,10 @@ const int ScreenshareLayers::kTl1SyncFlags = |
VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | |
VP8_EFLAG_NO_UPD_LAST; |
+// Always emit a frame with certain interval, even if bitrate targets have |
+// been exceeded. |
+const int ScreenshareLayers::kMaxFrameIntervalMs = 2000; |
+ |
ScreenshareLayers::ScreenshareLayers(int num_temporal_layers, |
uint8_t initial_tl0_pic_idx, |
Clock* clock) |
@@ -85,11 +89,12 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { |
int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp); |
int flags = 0; |
- |
if (active_layer_ == -1 || |
layers_[active_layer_].state != TemporalLayer::State::kDropped) { |
+ layers_[0].CheckFrameInterval(unwrapped_timestamp); |
if (layers_[0].debt_bytes_ > max_debt_bytes_) { |
// Must drop TL0, encode TL1 instead. |
+ layers_[1].CheckFrameInterval(unwrapped_timestamp); |
stefan-webrtc
2016/04/07 12:53:12
Do we want the same behavior in TL1, or should we
sprang_webrtc
2016/04/07 13:03:32
Yeah, I think only doing it for TL0 makes sense.
|
if (layers_[1].debt_bytes_ > max_debt_bytes_) { |
// Must drop both TL0 and TL1. |
active_layer_ = -1; |
@@ -104,6 +109,7 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { |
switch (active_layer_) { |
case 0: |
flags = kTl0Flags; |
+ layers_[0].last_emitted_timsetamp_ = unwrapped_timestamp; |
stefan-webrtc
2016/04/07 12:53:12
last_emitted_timestamp
sprang_webrtc
2016/04/07 13:03:32
Done.
|
break; |
case 1: |
if (TimeToSync(unwrapped_timestamp)) { |
@@ -112,6 +118,7 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { |
} else { |
flags = kTl1Flags; |
} |
+ layers_[1].last_emitted_timsetamp_ = unwrapped_timestamp; |
break; |
case -1: |
flags = -1; |
@@ -122,14 +129,13 @@ int ScreenshareLayers::EncodeFlags(uint32_t timestamp) { |
RTC_NOTREACHED(); |
} |
- // Make sure both frame droppers leak out bits. |
int64_t ts_diff; |
if (last_timestamp_ == -1) { |
ts_diff = kOneSecond90Khz / (frame_rate_ <= 0 ? 5 : frame_rate_); |
} else { |
ts_diff = unwrapped_timestamp - last_timestamp_; |
} |
- |
+ // Make sure both frame droppers leak out bits. |
layers_[0].UpdateDebt(ts_diff / 90); |
layers_[1].UpdateDebt(ts_diff / 90); |
last_timestamp_ = timestamp; |
@@ -302,6 +308,14 @@ void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) { |
} |
} |
+void ScreenshareLayers::TemporalLayer::CheckFrameInterval(int64_t timestamp) { |
+ if (last_emitted_timsetamp_ != -1 && |
+ (timestamp - last_emitted_timsetamp_) / 90 > kMaxFrameIntervalMs) { |
+ // Too long time has passed since the last frame was emitted, cancel debt. |
+ debt_bytes_ = 0; |
+ } |
+} |
+ |
void ScreenshareLayers::UpdateHistograms() { |
if (stats_.first_frame_time_ms_ == -1) |
return; |