Commit b6c1d435 authored by sergeyu's avatar sergeyu Committed by Commit bot

Account for expected capture and encode latency in WebrtcFrameSchedulerSimple

Previously when scheduling video frames the scheduler was taking into
account only expected pacer queue delay, but not the capturer/encoder
latency. Now the scheduler keeps queue of 5 most recent samples and uses
it to schedule each frame such that it's ready to be sent right after
the previous frame leaves the pacer.

This change improves bandwidth utilization in the ScrollPerformanceWebrtc test
from 30 to 50% without any effect on latency.

Review-Url: https://codereview.chromium.org/2366053002
Cr-Commit-Position: refs/heads/master@{#421341}
parent 9bcc88b3
......@@ -13,6 +13,9 @@ namespace protocol {
namespace {
// Number of samples used to estimate processing time for the next frame.
const int kStatsWindow = 5;
const int kTargetFrameRate = 30;
constexpr base::TimeDelta kTargetFrameInterval =
base::TimeDelta::FromMilliseconds(1000 / kTargetFrameRate);
......@@ -22,7 +25,8 @@ const int kTargetQuantizerForVp8TopOff = 30;
} // namespace
WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple() {}
WebrtcFrameSchedulerSimple::WebrtcFrameSchedulerSimple()
: frame_processing_delay_us_(kStatsWindow) {}
WebrtcFrameSchedulerSimple::~WebrtcFrameSchedulerSimple() {}
void WebrtcFrameSchedulerSimple::Start(const base::Closure& capture_callback) {
......@@ -82,6 +86,9 @@ void WebrtcFrameSchedulerSimple::OnFrameEncoded(
return;
}
frame_processing_delay_us_.Record(
(base::TimeTicks::Now() - last_capture_started_time_).InMicroseconds());
// Top-off until the target quantizer value is reached.
top_off_is_active_ = encoded_frame.quantizer > kTargetQuantizerForVp8TopOff;
......@@ -104,7 +111,10 @@ void WebrtcFrameSchedulerSimple::ScheduleNextFrame() {
// If this is not the first frame then capture next frame after the previous
// one has finished sending.
if (!last_frame_send_finish_time_.is_null()) {
delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ - now);
base::TimeDelta expected_processing_time =
base::TimeDelta::FromMicroseconds(frame_processing_delay_us_.Max());
delay = std::max(base::TimeDelta(), last_frame_send_finish_time_ -
expected_processing_time - now);
}
// Cap interval between frames to kTargetFrameInterval.
......
......@@ -8,6 +8,7 @@
#include "remoting/protocol/webrtc_frame_scheduler.h"
#include "base/timer/timer.h"
#include "remoting/base/running_samples.h"
namespace remoting {
namespace protocol {
......@@ -47,6 +48,9 @@ class WebrtcFrameSchedulerSimple : public WebrtcFrameScheduler {
// Set to true when encoding unchanged frames for top-off.
bool top_off_is_active_ = false;
// Accumulator for capture and encoder delay history.
RunningSamples frame_processing_delay_us_;
base::OneShotTimer capture_timer_;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment