Index: remoting/protocol/webrtc_frame_scheduler.cc |
diff --git a/remoting/protocol/webrtc_frame_scheduler.cc b/remoting/protocol/webrtc_frame_scheduler.cc |
deleted file mode 100644 |
index 0cab3d25bf04446d21471e51f1642e0cf359839e..0000000000000000000000000000000000000000 |
--- a/remoting/protocol/webrtc_frame_scheduler.cc |
+++ /dev/null |
@@ -1,229 +0,0 @@ |
-// Copyright 2016 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "remoting/protocol/webrtc_frame_scheduler.h" |
- |
-#include <algorithm> |
-#include <memory> |
- |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/single_thread_task_runner.h" |
-#include "base/threading/thread_task_runner_handle.h" |
-#include "remoting/base/constants.h" |
-#include "remoting/proto/video.pb.h" |
- |
-namespace remoting { |
-namespace protocol { |
- |
-namespace { |
- |
-// 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 |
-// the capture rate. |
-WebrtcFrameScheduler::WebrtcFrameScheduler( |
- scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, |
- std::unique_ptr<webrtc::DesktopCapturer> capturer, |
- WebrtcTransport* webrtc_transport, |
- std::unique_ptr<VideoEncoder> encoder) |
- : target_bitrate_kbps_(kDefaultTargetBitrateKbps), |
- main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
- encode_task_runner_(encode_task_runner), |
- capturer_(std::move(capturer)), |
- webrtc_transport_(webrtc_transport), |
- encoder_(std::move(encoder)), |
- weak_factory_(this) { |
- DCHECK(encode_task_runner_); |
- DCHECK(capturer_); |
- DCHECK(webrtc_transport_); |
- DCHECK(encoder_); |
- // Does not really start anything. Registers callback on this class. |
- capturer_->Start(this); |
- capture_timer_.reset(new base::RepeatingTimer()); |
-} |
- |
-WebrtcFrameScheduler::~WebrtcFrameScheduler() { |
- encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release()); |
-} |
- |
-void WebrtcFrameScheduler::Start() { |
- // Register for PLI requests. |
- 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))); |
-} |
- |
-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(); |
-} |
- |
-void WebrtcFrameScheduler::Pause(bool pause) { |
- if (pause) { |
- Stop(); |
- } else { |
- Start(); |
- } |
-} |
- |
-void WebrtcFrameScheduler::SetSizeCallback( |
- const VideoStream::SizeCallback& callback) { |
- size_callback_ = callback; |
-} |
- |
-void WebrtcFrameScheduler::SetKeyFrameRequest() { |
- VLOG(1) << "Request key frame"; |
- base::AutoLock lock(lock_); |
- key_frame_request_ = true; |
- if (!received_first_frame_request_) { |
- received_first_frame_request_ = true; |
- main_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&WebrtcFrameScheduler::StartCaptureTimer, |
- weak_factory_.GetWeakPtr())); |
- } |
-} |
- |
-void WebrtcFrameScheduler::StartCaptureTimer() { |
- capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this, |
- &WebrtcFrameScheduler::CaptureNextFrame); |
-} |
- |
-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_; |
- key_frame_request_ = false; |
- return key_frame_request; |
-} |
- |
-void WebrtcFrameScheduler::OnCaptureResult( |
- webrtc::DesktopCapturer::Result result, |
- std::unique_ptr<webrtc::DesktopFrame> frame) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- base::TimeTicks captured_ticks = base::TimeTicks::Now(); |
- int64_t capture_timestamp_ms = |
- (captured_ticks - base::TimeTicks()).InMilliseconds(); |
- capture_pending_ = false; |
- |
- // TODO(sergeyu): Handle ERROR_PERMANENT result here. |
- |
- if (encode_pending_) { |
- // TODO(isheriff): consider queuing here |
- VLOG(1) << "Dropping captured frame since encoder is still busy"; |
- return; |
- } |
- |
- last_capture_completed_ticks_ = captured_ticks; |
- |
- webrtc::DesktopVector dpi = |
- frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi) |
- : frame->dpi(); |
- |
- if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) { |
- frame_size_ = frame->size(); |
- frame_dpi_ = dpi; |
- if (!size_callback_.is_null()) |
- size_callback_.Run(frame_size_, frame_dpi_); |
- } |
- encode_pending_ = true; |
- task_tracker_.PostTaskAndReplyWithResult( |
- encode_task_runner_.get(), FROM_HERE, |
- base::Bind(&WebrtcFrameScheduler::EncodeFrame, encoder_.get(), |
- base::Passed(&frame), target_bitrate_kbps_, |
- ClearAndGetKeyFrameRequest(), capture_timestamp_ms), |
- base::Bind(&WebrtcFrameScheduler::OnFrameEncoded, |
- weak_factory_.GetWeakPtr())); |
-} |
- |
-void WebrtcFrameScheduler::CaptureNextFrame() { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- |
- if (capture_pending_ || encode_pending_) { |
- VLOG(1) << "Capture/encode still pending.."; |
- return; |
- } |
- |
- capture_pending_ = true; |
- VLOG(1) << "Capture next frame after " |
- << (base::TimeTicks::Now() - last_capture_started_ticks_) |
- .InMilliseconds(); |
- last_capture_started_ticks_ = base::TimeTicks::Now(); |
- capturer_->Capture(webrtc::DesktopRegion()); |
-} |
- |
-// static |
-std::unique_ptr<VideoPacket> WebrtcFrameScheduler::EncodeFrame( |
- VideoEncoder* encoder, |
- std::unique_ptr<webrtc::DesktopFrame> frame, |
- 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(); |
- return packet; |
-} |
- |
-void WebrtcFrameScheduler::OnFrameEncoded(std::unique_ptr<VideoPacket> packet) { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- encode_pending_ = false; |
- if (!packet) |
- return; |
- base::TimeTicks current = base::TimeTicks::Now(); |
- float 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)); |
- 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 |
-} // namespace remoting |