blob: d62aba0da8f2c4b3c0a2d05103e9f26f28652b58 [file] [log] [blame]
sergeyu2385cffe2014-09-19 19:23:411// 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
sergeyu89d088b2015-12-24 00:22:447#include <utility>
8
sergeyu2385cffe2014-09-19 19:23:419#include "base/bind.h"
Peter Kasting383640f52018-02-13 06:22:4010#include "base/bind_helpers.h"
sergeyu97568a8162015-02-24 18:00:5511#include "base/callback_helpers.h"
sergeyu2385cffe2014-09-19 19:23:4112#include "net/socket/stream_socket.h"
sergeyuf1005f62016-02-03 21:11:3013#include "remoting/base/compound_buffer.h"
sergeyu2385cffe2014-09-19 19:23:4114#include "remoting/base/constants.h"
sergeyu00a67b12016-04-01 00:07:0015#include "remoting/proto/control.pb.h"
sergeyu2385cffe2014-09-19 19:23:4116#include "remoting/proto/video.pb.h"
sergeyu00a67b12016-04-01 00:07:0017#include "remoting/protocol/client_stub.h"
sergeyuf1005f62016-02-03 21:11:3018#include "remoting/protocol/message_pipe.h"
sergeyu97568a8162015-02-24 18:00:5519#include "remoting/protocol/message_serialization.h"
sergeyu2385cffe2014-09-19 19:23:4120#include "remoting/protocol/video_stub.h"
21
22namespace remoting {
23namespace protocol {
24
sergeyu97568a8162015-02-24 18:00:5525struct ClientVideoDispatcher::PendingFrame {
26 PendingFrame(int frame_id)
27 : frame_id(frame_id),
28 done(false) {}
29 int frame_id;
30 bool done;
31};
32
sergeyu00a67b12016-04-01 00:07:0033ClientVideoDispatcher::ClientVideoDispatcher(VideoStub* video_stub,
34 ClientStub* client_stub)
sergeyu2385cffe2014-09-19 19:23:4135 : ChannelDispatcherBase(kVideoChannelName),
sergeyu97568a8162015-02-24 18:00:5536 video_stub_(video_stub),
sergeyu00a67b12016-04-01 00:07:0037 client_stub_(client_stub),
sergeyue61b68d2016-01-30 01:52:3638 weak_factory_(this) {}
sergeyu00a67b12016-04-01 00:07:0039
Chris Watkins6fe52aa2017-11-28 03:24:0540ClientVideoDispatcher::~ClientVideoDispatcher() = default;
sergeyu2385cffe2014-09-19 19:23:4141
sergeyud8af2ca2016-01-30 03:04:3642void ClientVideoDispatcher::OnIncomingMessage(
dcheng0765c492016-04-06 22:41:5343 std::unique_ptr<CompoundBuffer> message) {
44 std::unique_ptr<VideoPacket> video_packet =
sergeyud8af2ca2016-01-30 03:04:3645 ParseMessage<VideoPacket>(message.get());
46 if (!video_packet)
47 return;
48
sergeyu97568a8162015-02-24 18:00:5549 int frame_id = video_packet->frame_id();
50
51 if (!video_packet->has_frame_id()) {
Peter Kasting341e1fb2018-02-24 00:03:0152 video_stub_->ProcessVideoPacket(std::move(video_packet), base::DoNothing());
sergeyu97568a8162015-02-24 18:00:5553 return;
54 }
55
sergeyu00a67b12016-04-01 00:07:0056 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
jdoerried0539eeb2018-10-02 20:54:2993 auto pending_frame =
sergeyu97568a8162015-02-24 18:00:5594 pending_frames_.insert(pending_frames_.end(), PendingFrame(frame_id));
95
96 video_stub_->ProcessVideoPacket(
sergeyuaa6fa2342015-12-22 23:26:4897 std::move(video_packet),
Erik Jensen56d7f2e2019-02-20 01:38:5698 base::BindOnce(&ClientVideoDispatcher::OnPacketDone,
99 weak_factory_.GetWeakPtr(), pending_frame));
sergeyu97568a8162015-02-24 18:00:55100}
101
102void 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);
sergeyuf1005f62016-02-03 21:11:30113 message_pipe()->Send(&ack_message, base::Closure());
sergeyu97568a8162015-02-24 18:00:55114 pending_frames_.pop_front();
115 }
116}
117
sergeyu2385cffe2014-09-19 19:23:41118} // namespace protocol
119} // namespace remoting