| 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
|
|
|