Chromium Code Reviews| Index: remoting/host/video_scheduler.cc |
| diff --git a/remoting/host/video_scheduler.cc b/remoting/host/video_scheduler.cc |
| index 7fc1983128d8d0c36604e502b64e08fbd2a88135..537fad390d56a301f24b6f6feffa551c45a9a5dc 100644 |
| --- a/remoting/host/video_scheduler.cc |
| +++ b/remoting/host/video_scheduler.cc |
| @@ -30,6 +30,10 @@ namespace remoting { |
| // 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 frame being sent. |
|
Wez
2014/05/24 05:57:08
typo: frame -> frames
Sergey Ulanov
2014/05/24 09:06:28
Done.
|
| +static const int kKeepAlivePacketIntervalMs = 500; |
| + |
| VideoScheduler::VideoScheduler( |
| scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, |
| scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, |
| @@ -68,16 +72,22 @@ void VideoScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) { |
| 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_task_runner_->PostTask( |
| - FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, |
| - base::Passed(&owned_frame), sequence_number_)); |
| + // 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_)); |
| + } |
| // If a frame was skipped, try to capture it again. |
| if (did_skip_frame_) { |
| @@ -123,8 +133,10 @@ void VideoScheduler::Stop() { |
| 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 @@ void VideoScheduler::StartOnCaptureThread() { |
| 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 @@ void VideoScheduler::SendVideoPacket(scoped_ptr<VideoPacket> packet) { |
| 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,17 +313,7 @@ void VideoScheduler::EncodeFrame( |
| scoped_ptr<webrtc::DesktopFrame> frame, |
| int64 sequence_number) { |
| DCHECK(encode_task_runner_->BelongsToCurrentThread()); |
| - |
| - // 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; |
| - } |
| + DCHECK(!frame->updated_region().is_empty()); |
| scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame); |
| packet->set_client_sequence_number(sequence_number); |