sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "remoting/protocol/client_video_dispatcher.h" |
| 6 | |
sergeyu | 89d088b | 2015-12-24 00:22:44 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 9 | #include "base/bind.h" |
Peter Kasting | 383640f5 | 2018-02-13 06:22:40 | [diff] [blame] | 10 | #include "base/bind_helpers.h" |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 11 | #include "base/callback_helpers.h" |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 12 | #include "net/socket/stream_socket.h" |
sergeyu | f1005f6 | 2016-02-03 21:11:30 | [diff] [blame] | 13 | #include "remoting/base/compound_buffer.h" |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 14 | #include "remoting/base/constants.h" |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 15 | #include "remoting/proto/control.pb.h" |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 16 | #include "remoting/proto/video.pb.h" |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 17 | #include "remoting/protocol/client_stub.h" |
sergeyu | f1005f6 | 2016-02-03 21:11:30 | [diff] [blame] | 18 | #include "remoting/protocol/message_pipe.h" |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 19 | #include "remoting/protocol/message_serialization.h" |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 20 | #include "remoting/protocol/video_stub.h" |
| 21 | |
| 22 | namespace remoting { |
| 23 | namespace protocol { |
| 24 | |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 25 | struct ClientVideoDispatcher::PendingFrame { |
| 26 | PendingFrame(int frame_id) |
| 27 | : frame_id(frame_id), |
| 28 | done(false) {} |
| 29 | int frame_id; |
| 30 | bool done; |
| 31 | }; |
| 32 | |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 33 | ClientVideoDispatcher::ClientVideoDispatcher(VideoStub* video_stub, |
| 34 | ClientStub* client_stub) |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 35 | : ChannelDispatcherBase(kVideoChannelName), |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 36 | video_stub_(video_stub), |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 37 | client_stub_(client_stub), |
sergeyu | e61b68d | 2016-01-30 01:52:36 | [diff] [blame] | 38 | weak_factory_(this) {} |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 39 | |
Chris Watkins | 6fe52aa | 2017-11-28 03:24:05 | [diff] [blame] | 40 | ClientVideoDispatcher::~ClientVideoDispatcher() = default; |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 41 | |
sergeyu | d8af2ca | 2016-01-30 03:04:36 | [diff] [blame] | 42 | void ClientVideoDispatcher::OnIncomingMessage( |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 43 | std::unique_ptr<CompoundBuffer> message) { |
| 44 | std::unique_ptr<VideoPacket> video_packet = |
sergeyu | d8af2ca | 2016-01-30 03:04:36 | [diff] [blame] | 45 | ParseMessage<VideoPacket>(message.get()); |
| 46 | if (!video_packet) |
| 47 | return; |
| 48 | |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 49 | int frame_id = video_packet->frame_id(); |
| 50 | |
| 51 | if (!video_packet->has_frame_id()) { |
Peter Kasting | 341e1fb | 2018-02-24 00:03:01 | [diff] [blame] | 52 | video_stub_->ProcessVideoPacket(std::move(video_packet), base::DoNothing()); |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 53 | return; |
| 54 | } |
| 55 | |
sergeyu | 00a67b1 | 2016-04-01 00:07:00 | [diff] [blame] | 56 | bool resolution_changed = false; |
| 57 | |
| 58 | if (video_packet->format().has_screen_width() && |
| 59 | video_packet->format().has_screen_height()) { |
| 60 | webrtc::DesktopSize frame_size(video_packet->format().screen_width(), |
| 61 | video_packet->format().screen_height()); |
| 62 | if (!screen_size_.equals(frame_size)) { |
| 63 | screen_size_ = frame_size; |
| 64 | resolution_changed = true; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | if (video_packet->format().has_x_dpi() && |
| 69 | video_packet->format().has_y_dpi()) { |
| 70 | webrtc::DesktopVector screen_dpi(video_packet->format().x_dpi(), |
| 71 | video_packet->format().y_dpi()); |
| 72 | if (!screen_dpi_.equals(screen_dpi)) { |
| 73 | screen_dpi_ = screen_dpi; |
| 74 | resolution_changed = true; |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | // Simulate DesktopLayout message whenever screen size/resolution changes. |
| 79 | if (resolution_changed) { |
| 80 | VideoLayout layout; |
| 81 | VideoTrackLayout* video_track = layout.add_video_track(); |
| 82 | video_track->set_position_x(0); |
| 83 | video_track->set_position_y(0); |
| 84 | video_track->set_width(screen_size_.width() * kDefaultDpi / |
| 85 | screen_dpi_.x()); |
| 86 | video_track->set_height(screen_size_.height() * kDefaultDpi / |
| 87 | screen_dpi_.y()); |
| 88 | video_track->set_x_dpi(screen_dpi_.x()); |
| 89 | video_track->set_y_dpi(screen_dpi_.y()); |
| 90 | client_stub_->SetVideoLayout(layout); |
| 91 | } |
| 92 | |
jdoerrie | d0539eeb | 2018-10-02 20:54:29 | [diff] [blame] | 93 | auto pending_frame = |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 94 | pending_frames_.insert(pending_frames_.end(), PendingFrame(frame_id)); |
| 95 | |
| 96 | video_stub_->ProcessVideoPacket( |
sergeyu | aa6fa234 | 2015-12-22 23:26:48 | [diff] [blame] | 97 | std::move(video_packet), |
Erik Jensen | 56d7f2e | 2019-02-20 01:38:56 | [diff] [blame] | 98 | base::BindOnce(&ClientVideoDispatcher::OnPacketDone, |
| 99 | weak_factory_.GetWeakPtr(), pending_frame)); |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | void ClientVideoDispatcher::OnPacketDone( |
| 103 | PendingFramesList::iterator pending_frame) { |
| 104 | // Mark the frame as done. |
| 105 | DCHECK(!pending_frame->done); |
| 106 | pending_frame->done = true; |
| 107 | |
| 108 | // Send VideoAck for all packets in the head of the queue that have finished |
| 109 | // rendering. |
| 110 | while (!pending_frames_.empty() && pending_frames_.front().done) { |
| 111 | VideoAck ack_message; |
| 112 | ack_message.set_frame_id(pending_frames_.front().frame_id); |
sergeyu | f1005f6 | 2016-02-03 21:11:30 | [diff] [blame] | 113 | message_pipe()->Send(&ack_message, base::Closure()); |
sergeyu | 97568a816 | 2015-02-24 18:00:55 | [diff] [blame] | 114 | pending_frames_.pop_front(); |
| 115 | } |
| 116 | } |
| 117 | |
sergeyu | 2385cffe | 2014-09-19 19:23:41 | [diff] [blame] | 118 | } // namespace protocol |
| 119 | } // namespace remoting |