| Index: remoting/host/video_scheduler.cc
|
| ===================================================================
|
| --- remoting/host/video_scheduler.cc (revision 273938)
|
| +++ remoting/host/video_scheduler.cc (working copy)
|
| @@ -30,6 +30,10 @@
|
| // TODO(hclam): Move this value to CaptureScheduler.
|
| static const int kMaxPendingFrames = 2;
|
|
|
| +// Interval between empty keep-alive frames. These frames are sent only
|
| +// when there are no real video frames being sent.
|
| +static const int kKeepAlivePacketIntervalMs = 500;
|
| +
|
| VideoScheduler::VideoScheduler(
|
| scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
|
| scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
|
| @@ -68,17 +72,23 @@
|
|
|
| capture_pending_ = false;
|
|
|
| + if (!frame) {
|
| + LOG(ERROR) << "Capture failed.";
|
| + return;
|
| + }
|
| +
|
| scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
|
|
|
| - if (frame) {
|
| - scheduler_.RecordCaptureTime(
|
| - base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
|
| + scheduler_.RecordCaptureTime(
|
| + base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
|
| +
|
| + // Encode and send only non-empty frames.
|
| + if (!frame->updated_region().is_empty()) {
|
| + encode_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this,
|
| + base::Passed(&owned_frame), sequence_number_));
|
| }
|
|
|
| - encode_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this,
|
| - base::Passed(&owned_frame), sequence_number_));
|
| -
|
| // If a frame was skipped, try to capture it again.
|
| if (did_skip_frame_) {
|
| capture_task_runner_->PostTask(
|
| @@ -123,8 +133,10 @@
|
| cursor_stub_ = NULL;
|
| video_stub_ = NULL;
|
|
|
| - capture_task_runner_->PostTask(FROM_HERE,
|
| - base::Bind(&VideoScheduler::StopOnCaptureThread, this));
|
| + keep_alive_timer_.reset();
|
| +
|
| + capture_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&VideoScheduler::StopOnCaptureThread, this));
|
| }
|
|
|
| void VideoScheduler::Pause(bool pause) {
|
| @@ -172,6 +184,9 @@
|
| capturer_->Start(this);
|
|
|
| capture_timer_.reset(new base::OneShotTimer<VideoScheduler>());
|
| + keep_alive_timer_.reset(new base::DelayTimer<VideoScheduler>(
|
| + FROM_HERE, base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
|
| + this, &VideoScheduler::SendKeepAlivePacket));
|
|
|
| // Capture first frame immedately.
|
| CaptureNextFrame();
|
| @@ -249,19 +264,39 @@
|
| return;
|
|
|
| video_stub_->ProcessVideoPacket(
|
| - packet.Pass(), base::Bind(&VideoScheduler::VideoFrameSentCallback, this));
|
| + packet.Pass(), base::Bind(&VideoScheduler::OnVideoPacketSent, this));
|
| }
|
|
|
| -void VideoScheduler::VideoFrameSentCallback() {
|
| +void VideoScheduler::OnVideoPacketSent() {
|
| DCHECK(network_task_runner_->BelongsToCurrentThread());
|
|
|
| if (!video_stub_)
|
| return;
|
|
|
| + keep_alive_timer_->Reset();
|
| +
|
| capture_task_runner_->PostTask(
|
| FROM_HERE, base::Bind(&VideoScheduler::FrameCaptureCompleted, this));
|
| }
|
|
|
| +void VideoScheduler::SendKeepAlivePacket() {
|
| + DCHECK(network_task_runner_->BelongsToCurrentThread());
|
| +
|
| + if (!video_stub_)
|
| + return;
|
| +
|
| + video_stub_->ProcessVideoPacket(
|
| + scoped_ptr<VideoPacket>(new VideoPacket()),
|
| + base::Bind(&VideoScheduler::OnKeepAlivePacketSent, this));
|
| +}
|
| +
|
| +void VideoScheduler::OnKeepAlivePacketSent() {
|
| + DCHECK(network_task_runner_->BelongsToCurrentThread());
|
| +
|
| + if (keep_alive_timer_)
|
| + keep_alive_timer_->Reset();
|
| +}
|
| +
|
| void VideoScheduler::SendCursorShape(
|
| scoped_ptr<protocol::CursorShapeInfo> cursor_shape) {
|
| DCHECK(network_task_runner_->BelongsToCurrentThread());
|
| @@ -278,18 +313,8 @@
|
| scoped_ptr<webrtc::DesktopFrame> frame,
|
| int64 sequence_number) {
|
| DCHECK(encode_task_runner_->BelongsToCurrentThread());
|
| + DCHECK(!frame->updated_region().is_empty());
|
|
|
| - // If there is nothing to encode then send an empty keep-alive packet.
|
| - if (!frame || frame->updated_region().is_empty()) {
|
| - scoped_ptr<VideoPacket> packet(new VideoPacket());
|
| - packet->set_client_sequence_number(sequence_number);
|
| - network_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this,
|
| - base::Passed(&packet)));
|
| - capture_task_runner_->DeleteSoon(FROM_HERE, frame.release());
|
| - return;
|
| - }
|
| -
|
| scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame);
|
| packet->set_client_sequence_number(sequence_number);
|
|
|
|
|