Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Unified Diff: remoting/protocol/webrtc_frame_scheduler.cc

Issue 1908203002: Adapt encoder behavior to target bitrate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unnecessary code Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler.h ('k') | remoting/protocol/webrtc_transport.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/protocol/webrtc_frame_scheduler.cc
diff --git a/remoting/protocol/webrtc_frame_scheduler.cc b/remoting/protocol/webrtc_frame_scheduler.cc
index bdc602272304ff5a107ee859df130ff75185e11c..f1671378a01b1cc1aee3183422209256ddc7962c 100644
--- a/remoting/protocol/webrtc_frame_scheduler.cc
+++ b/remoting/protocol/webrtc_frame_scheduler.cc
@@ -4,6 +4,7 @@
#include "remoting/protocol/webrtc_frame_scheduler.h"
+#include <algorithm>
#include <memory>
#include "base/logging.h"
@@ -13,6 +14,19 @@
namespace remoting {
namespace protocol {
+namespace {
+
+// Target quantizer at which stop the encoding top-off.
+const int kTargetQuantizerForTopOff = 30;
+
+// Max Quantizer value.
+const int kMaxQuantizer = 63;
+
+// Default target bitrate in kbps
+const int kDefaultTargetBitrateKbps = 1000;
+
+} // namespace
+
// The frame scheduler currently uses a simple polling technique
// at 30 FPS to capture, encode and send frames over webrtc transport.
// An improved solution will use target bitrate feedback to pace out
@@ -22,7 +36,9 @@ WebRtcFrameScheduler::WebRtcFrameScheduler(
std::unique_ptr<webrtc::DesktopCapturer> capturer,
WebrtcTransport* webrtc_transport,
std::unique_ptr<VideoEncoder> encoder)
- : encode_task_runner_(encode_task_runner),
+ : target_bitrate_kbps_(kDefaultTargetBitrateKbps),
+ last_quantizer_(kMaxQuantizer),
+ encode_task_runner_(encode_task_runner),
capturer_(std::move(capturer)),
webrtc_transport_(webrtc_transport),
encoder_(std::move(encoder)),
@@ -45,6 +61,10 @@ void WebRtcFrameScheduler::Start() {
webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
base::Bind(&WebRtcFrameScheduler::SetKeyFrameRequest,
base::Unretained(this)));
+ // Register for target bitrate notifications.
+ webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback(
+ base::Bind(&WebRtcFrameScheduler::SetTargetBitrate,
+ base::Unretained(this)));
capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this,
&WebRtcFrameScheduler::CaptureNextFrame);
}
@@ -53,6 +73,8 @@ void WebRtcFrameScheduler::Stop() {
// Clear PLI request callback.
webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
base::Closure());
+ webrtc_transport_->video_encoder_factory()->SetTargetBitrateCallback(
+ TargetBitrateCallback());
// Cancel any pending encode.
task_tracker_.TryCancelAll();
capture_timer_->Stop();
@@ -77,6 +99,12 @@ void WebRtcFrameScheduler::SetKeyFrameRequest() {
key_frame_request_ = true;
}
+void WebRtcFrameScheduler::SetTargetBitrate(int target_bitrate_kbps) {
+ VLOG(1) << "Set Target bitrate " << target_bitrate_kbps;
+ base::AutoLock lock(lock_);
+ target_bitrate_kbps_ = target_bitrate_kbps;
+}
+
bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
base::AutoLock lock(lock_);
bool key_frame_request = key_frame_request_;
@@ -87,8 +115,9 @@ bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
DCHECK(thread_checker_.CalledOnValidThread());
- VLOG(1) << "Capture overhead "
- << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
+ base::TimeTicks captured_ticks = base::TimeTicks::Now();
+ int64_t capture_timestamp_ms =
+ (captured_ticks - base::TimeTicks()).InMilliseconds();
capture_pending_ = false;
std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
@@ -98,9 +127,14 @@ void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
VLOG(1) << "Dropping captured frame since encoder is still busy";
return;
}
- if (!frame || frame->updated_region().is_empty())
+
+ // If unchanged and does not need top-off, return.
+ if (!frame || (frame->updated_region().is_empty() &&
+ last_quantizer_ <= kTargetQuantizerForTopOff))
return;
+ last_capture_completed_ticks_ = captured_ticks;
+
webrtc::DesktopVector dpi =
frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
: frame->dpi();
@@ -115,8 +149,8 @@ void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
task_tracker_.PostTaskAndReplyWithResult(
encode_task_runner_.get(), FROM_HERE,
base::Bind(&WebRtcFrameScheduler::EncodeFrame, encoder_.get(),
- base::Passed(std::move(owned_frame)),
- ClearAndGetKeyFrameRequest()),
+ base::Passed(std::move(owned_frame)), target_bitrate_kbps_,
+ ClearAndGetKeyFrameRequest(), capture_timestamp_ms),
base::Bind(&WebRtcFrameScheduler::OnFrameEncoded,
weak_factory_.GetWeakPtr()));
}
@@ -130,8 +164,9 @@ void WebRtcFrameScheduler::CaptureNextFrame() {
}
capture_pending_ = true;
VLOG(1) << "Capture next frame after "
- << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
- last_capture_ticks_ = base::TimeTicks::Now();
+ << (base::TimeTicks::Now() - last_capture_started_ticks_)
+ .InMilliseconds();
+ last_capture_started_ticks_ = base::TimeTicks::Now();
capturer_->Capture(webrtc::DesktopRegion());
}
@@ -139,19 +174,27 @@ void WebRtcFrameScheduler::CaptureNextFrame() {
std::unique_ptr<VideoPacket> WebRtcFrameScheduler::EncodeFrame(
VideoEncoder* encoder,
std::unique_ptr<webrtc::DesktopFrame> frame,
- bool key_frame_request) {
+ uint32_t target_bitrate_kbps,
+ bool key_frame_request,
+ int64_t capture_time_ms) {
uint32_t flags = 0;
if (key_frame_request)
flags |= VideoEncoder::REQUEST_KEY_FRAME;
base::TimeTicks current = base::TimeTicks::Now();
+ encoder->UpdateTargetBitrate(target_bitrate_kbps);
std::unique_ptr<VideoPacket> packet = encoder->Encode(*frame, flags);
if (!packet)
return nullptr;
+ // TODO(isheriff): Note that while VideoPacket capture time is supposed
+ // to be capture duration, we (ab)use it for capture timestamp here. This
+ // will go away when we move away from VideoPacket.
+ packet->set_capture_time_ms(capture_time_ms);
VLOG(1) << "Encode duration "
<< (base::TimeTicks::Now() - current).InMilliseconds()
- << " payload size " << packet->data().size();
+ << " payload size " << packet->data().size() << " quantizer "
+ << packet->quantizer();
return packet;
}
@@ -160,16 +203,26 @@ void WebRtcFrameScheduler::OnFrameEncoded(std::unique_ptr<VideoPacket> packet) {
encode_pending_ = false;
if (!packet)
return;
- int64_t capture_timestamp_ms =
- (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
+ last_quantizer_ = packet->quantizer();
base::TimeTicks current = base::TimeTicks::Now();
+ uint32_t encoded_bits = packet->data().size() * 8.0;
+
+ // Simplistic adaptation of frame polling in the range 5 FPS to 30 FPS.
+ uint32_t next_sched_ms = std::max(
+ 33, std::min(static_cast<int>(encoded_bits / target_bitrate_kbps_), 200));
// TODO(isheriff): Investigate why first frame fails to send at times.
// This gets resolved through a PLI request.
- webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
- capture_timestamp_ms, std::move(packet));
-
- VLOG(1) << "Send duration "
- << (base::TimeTicks::Now() - current).InMilliseconds();
+ if (webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
+ std::move(packet)) >= 0) {
+ VLOG(1) << " Send duration "
+ << (base::TimeTicks::Now() - current).InMilliseconds()
+ << "next sched " << next_sched_ms;
+ } else {
+ LOG(ERROR) << "SendEncodedFrame() failed";
+ }
+ capture_timer_->Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(next_sched_ms), this,
+ &WebRtcFrameScheduler::CaptureNextFrame);
}
} // namespace protocol
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler.h ('k') | remoting/protocol/webrtc_transport.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698