Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/client/chromoting_client.h" | 5 #include "remoting/client/chromoting_client.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "remoting/client/chromoting_view.h" | 8 #include "remoting/client/chromoting_view.h" |
| 9 #include "remoting/client/client_context.h" | 9 #include "remoting/client/client_context.h" |
| 10 #include "remoting/client/rectangle_update_decoder.h" | 10 #include "remoting/client/rectangle_update_decoder.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 : packet(packet.release()), done(done) { | 24 : packet(packet.release()), done(done) { |
| 25 } | 25 } |
| 26 | 26 |
| 27 ChromotingClient::QueuedVideoPacket::~QueuedVideoPacket() { | 27 ChromotingClient::QueuedVideoPacket::~QueuedVideoPacket() { |
| 28 } | 28 } |
| 29 | 29 |
| 30 ChromotingClient::ChromotingClient(const ClientConfig& config, | 30 ChromotingClient::ChromotingClient(const ClientConfig& config, |
| 31 ClientContext* context, | 31 ClientContext* context, |
| 32 protocol::ConnectionToHost* connection, | 32 protocol::ConnectionToHost* connection, |
| 33 ChromotingView* view, | 33 ChromotingView* view, |
| 34 RectangleUpdateDecoder* rectangle_decoder, | 34 RectangleUpdateDecoder* rectangle_decoder) |
| 35 const base::Closure& client_done) | |
| 36 : config_(config), | 35 : config_(config), |
| 37 context_(context), | 36 context_(context), |
| 38 connection_(connection), | 37 connection_(connection), |
| 39 view_(view), | 38 view_(view), |
| 40 rectangle_decoder_(rectangle_decoder), | 39 rectangle_decoder_(rectangle_decoder), |
| 41 client_done_(client_done), | |
| 42 packet_being_processed_(false), | 40 packet_being_processed_(false), |
| 43 last_sequence_number_(0), | 41 last_sequence_number_(0), |
| 44 thread_proxy_(context_->network_message_loop()) { | 42 thread_proxy_(context_->main_task_runner()) { |
| 45 } | 43 } |
| 46 | 44 |
| 47 ChromotingClient::~ChromotingClient() { | 45 ChromotingClient::~ChromotingClient() { |
| 48 } | 46 } |
| 49 | 47 |
| 50 void ChromotingClient::Start( | 48 void ChromotingClient::Start( |
| 51 scoped_refptr<XmppProxy> xmpp_proxy, | 49 scoped_refptr<XmppProxy> xmpp_proxy, |
| 52 scoped_ptr<protocol::TransportFactory> transport_factory) { | 50 scoped_ptr<protocol::TransportFactory> transport_factory) { |
| 53 DCHECK(message_loop()->BelongsToCurrentThread()); | 51 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 54 | 52 |
| 55 scoped_ptr<protocol::Authenticator> authenticator; | 53 scoped_ptr<protocol::Authenticator> authenticator; |
| 56 if (config_.use_v1_authenticator) { | 54 if (config_.use_v1_authenticator) { |
| 57 authenticator.reset(new protocol::V1ClientAuthenticator( | 55 authenticator.reset(new protocol::V1ClientAuthenticator( |
| 58 config_.local_jid, config_.shared_secret)); | 56 config_.local_jid, config_.shared_secret)); |
| 59 } else { | 57 } else { |
| 60 authenticator = protocol::NegotiatingAuthenticator::CreateForClient( | 58 authenticator = protocol::NegotiatingAuthenticator::CreateForClient( |
| 61 config_.authentication_tag, | 59 config_.authentication_tag, |
| 62 config_.shared_secret, config_.authentication_methods); | 60 config_.shared_secret, config_.authentication_methods); |
| 63 } | 61 } |
| 64 | 62 |
| 65 connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, | 63 connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, |
| 66 config_.host_public_key, transport_factory.Pass(), | 64 config_.host_public_key, transport_factory.Pass(), |
| 67 authenticator.Pass(), this, this, this, this); | 65 authenticator.Pass(), this, this, this, this); |
| 68 | 66 |
| 69 if (!view_->Initialize()) { | 67 view_->Initialize(); |
| 70 ClientDone(); | |
| 71 } | |
| 72 } | 68 } |
| 73 | 69 |
| 74 void ChromotingClient::Stop(const base::Closure& shutdown_task) { | 70 void ChromotingClient::Stop(const base::Closure& shutdown_task) { |
| 75 if (!message_loop()->BelongsToCurrentThread()) { | 71 if (!task_runner()->BelongsToCurrentThread()) { |
|
Wez
2012/05/26 00:18:40
Which other threads does the client get Stop()ped
Sergey Ulanov
2012/05/30 01:07:07
This is no longer necessary. Replaced with a DCHEC
| |
| 76 message_loop()->PostTask( | 72 task_runner()->PostTask( |
| 77 FROM_HERE, base::Bind(&ChromotingClient::Stop, | 73 FROM_HERE, base::Bind(&ChromotingClient::Stop, |
| 78 base::Unretained(this), shutdown_task)); | 74 base::Unretained(this), shutdown_task)); |
| 79 return; | 75 return; |
| 80 } | 76 } |
| 81 | 77 |
| 82 // Drop all pending packets. | 78 // Drop all pending packets. |
| 83 while(!received_packets_.empty()) { | 79 while(!received_packets_.empty()) { |
| 84 delete received_packets_.front().packet; | 80 delete received_packets_.front().packet; |
| 85 received_packets_.front().done.Run(); | 81 received_packets_.front().done.Run(); |
| 86 received_packets_.pop_front(); | 82 received_packets_.pop_front(); |
| 87 } | 83 } |
| 88 | 84 |
| 89 connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected, | 85 connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected, |
| 90 base::Unretained(this), shutdown_task)); | 86 base::Unretained(this), shutdown_task)); |
| 91 } | 87 } |
| 92 | 88 |
| 93 void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) { | 89 void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) { |
| 94 view_->TearDown(); | 90 view_->TearDown(); |
| 95 | 91 |
| 96 shutdown_task.Run(); | 92 shutdown_task.Run(); |
| 97 } | 93 } |
| 98 | 94 |
| 99 void ChromotingClient::ClientDone() { | |
| 100 if (!client_done_.is_null()) { | |
| 101 message_loop()->PostTask(FROM_HERE, client_done_); | |
| 102 client_done_.Reset(); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 ChromotingStats* ChromotingClient::GetStats() { | 95 ChromotingStats* ChromotingClient::GetStats() { |
| 96 DCHECK(task_runner()->BelongsToCurrentThread()); | |
| 107 return &stats_; | 97 return &stats_; |
| 108 } | 98 } |
| 109 | 99 |
| 110 void ChromotingClient::InjectClipboardEvent( | 100 void ChromotingClient::InjectClipboardEvent( |
| 111 const protocol::ClipboardEvent& event) { | 101 const protocol::ClipboardEvent& event) { |
| 102 DCHECK(task_runner()->BelongsToCurrentThread()); | |
| 112 view_->GetClipboardStub()->InjectClipboardEvent(event); | 103 view_->GetClipboardStub()->InjectClipboardEvent(event); |
| 113 } | 104 } |
| 114 | 105 |
| 115 void ChromotingClient::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, | 106 void ChromotingClient::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
| 116 const base::Closure& done) { | 107 const base::Closure& done) { |
| 117 DCHECK(message_loop()->BelongsToCurrentThread()); | 108 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 118 | 109 |
| 119 // If the video packet is empty then drop it. Empty packets are used to | 110 // If the video packet is empty then drop it. Empty packets are used to |
| 120 // maintain activity on the network. | 111 // maintain activity on the network. |
| 121 if (!packet->has_data() || packet->data().size() == 0) { | 112 if (!packet->has_data() || packet->data().size() == 0) { |
| 122 done.Run(); | 113 done.Run(); |
| 123 return; | 114 return; |
| 124 } | 115 } |
| 125 | 116 |
| 126 // Add one frame to the counter. | 117 // Add one frame to the counter. |
| 127 stats_.video_frame_rate()->Record(1); | 118 stats_.video_frame_rate()->Record(1); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 140 base::Time::FromInternalValue(packet->client_sequence_number()); | 131 base::Time::FromInternalValue(packet->client_sequence_number()); |
| 141 stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); | 132 stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); |
| 142 } | 133 } |
| 143 | 134 |
| 144 received_packets_.push_back(QueuedVideoPacket(packet.Pass(), done)); | 135 received_packets_.push_back(QueuedVideoPacket(packet.Pass(), done)); |
| 145 if (!packet_being_processed_) | 136 if (!packet_being_processed_) |
| 146 DispatchPacket(); | 137 DispatchPacket(); |
| 147 } | 138 } |
| 148 | 139 |
| 149 int ChromotingClient::GetPendingPackets() { | 140 int ChromotingClient::GetPendingPackets() { |
| 141 DCHECK(task_runner()->BelongsToCurrentThread()); | |
| 150 return received_packets_.size(); | 142 return received_packets_.size(); |
| 151 } | 143 } |
| 152 | 144 |
| 153 void ChromotingClient::DispatchPacket() { | 145 void ChromotingClient::DispatchPacket() { |
| 154 DCHECK(message_loop()->BelongsToCurrentThread()); | 146 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 155 CHECK(!packet_being_processed_); | 147 CHECK(!packet_being_processed_); |
| 156 | 148 |
| 157 if (received_packets_.empty()) { | 149 if (received_packets_.empty()) { |
| 158 // Nothing to do! | 150 // Nothing to do! |
| 159 return; | 151 return; |
| 160 } | 152 } |
| 161 | 153 |
| 162 scoped_ptr<VideoPacket> packet(received_packets_.front().packet); | 154 scoped_ptr<VideoPacket> packet(received_packets_.front().packet); |
| 163 received_packets_.front().packet = NULL; | 155 received_packets_.front().packet = NULL; |
| 164 packet_being_processed_ = true; | 156 packet_being_processed_ = true; |
| 165 | 157 |
| 166 // Measure the latency between the last packet being received and presented. | 158 // Measure the latency between the last packet being received and presented. |
| 167 bool last_packet = (packet->flags() & VideoPacket::LAST_PACKET) != 0; | 159 bool last_packet = (packet->flags() & VideoPacket::LAST_PACKET) != 0; |
| 168 base::Time decode_start; | 160 base::Time decode_start; |
| 169 if (last_packet) | 161 if (last_packet) |
| 170 decode_start = base::Time::Now(); | 162 decode_start = base::Time::Now(); |
| 171 | 163 |
| 172 rectangle_decoder_->DecodePacket( | 164 rectangle_decoder_->DecodePacket( |
| 173 packet.Pass(), | 165 packet.Pass(), |
| 174 base::Bind(&ChromotingClient::OnPacketDone, base::Unretained(this), | 166 base::Bind(&ChromotingClient::OnPacketDone, base::Unretained(this), |
| 175 last_packet, decode_start)); | 167 last_packet, decode_start)); |
| 176 } | 168 } |
| 177 | 169 |
| 178 void ChromotingClient::OnConnectionState( | 170 void ChromotingClient::OnConnectionState( |
| 179 protocol::ConnectionToHost::State state, | 171 protocol::ConnectionToHost::State state, |
| 180 protocol::ErrorCode error) { | 172 protocol::ErrorCode error) { |
| 181 DCHECK(message_loop()->BelongsToCurrentThread()); | 173 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 182 VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; | 174 VLOG(1) << "ChromotingClient::OnConnectionState(" << state << ")"; |
| 183 if (state == protocol::ConnectionToHost::CONNECTED) | 175 if (state == protocol::ConnectionToHost::CONNECTED) |
| 184 Initialize(); | 176 Initialize(); |
| 185 view_->SetConnectionState(state, error); | 177 view_->SetConnectionState(state, error); |
| 186 } | 178 } |
| 187 | 179 |
| 188 base::MessageLoopProxy* ChromotingClient::message_loop() { | 180 base::SingleThreadTaskRunner* ChromotingClient::task_runner() { |
| 189 return context_->network_message_loop(); | 181 return context_->main_task_runner(); |
| 190 } | 182 } |
| 191 | 183 |
| 192 void ChromotingClient::OnPacketDone(bool last_packet, | 184 void ChromotingClient::OnPacketDone(bool last_packet, |
| 193 base::Time decode_start) { | 185 base::Time decode_start) { |
| 194 if (!message_loop()->BelongsToCurrentThread()) { | 186 if (!task_runner()->BelongsToCurrentThread()) { |
| 195 thread_proxy_.PostTask(FROM_HERE, base::Bind( | 187 thread_proxy_.PostTask(FROM_HERE, base::Bind( |
| 196 &ChromotingClient::OnPacketDone, base::Unretained(this), | 188 &ChromotingClient::OnPacketDone, base::Unretained(this), |
| 197 last_packet, decode_start)); | 189 last_packet, decode_start)); |
| 198 return; | 190 return; |
| 199 } | 191 } |
| 200 | 192 |
| 201 // Record the latency between the final packet being received and | 193 // Record the latency between the final packet being received and |
| 202 // presented. | 194 // presented. |
| 203 if (last_packet) { | 195 if (last_packet) { |
| 204 stats_.video_decode_ms()->Record( | 196 stats_.video_decode_ms()->Record( |
| 205 (base::Time::Now() - decode_start).InMilliseconds()); | 197 (base::Time::Now() - decode_start).InMilliseconds()); |
| 206 } | 198 } |
| 207 | 199 |
| 208 received_packets_.front().done.Run(); | 200 received_packets_.front().done.Run(); |
| 209 received_packets_.pop_front(); | 201 received_packets_.pop_front(); |
| 210 | 202 |
| 211 packet_being_processed_ = false; | 203 packet_being_processed_ = false; |
| 212 | 204 |
| 213 // Process the next video packet. | 205 // Process the next video packet. |
| 214 DispatchPacket(); | 206 DispatchPacket(); |
| 215 } | 207 } |
| 216 | 208 |
| 217 void ChromotingClient::Initialize() { | 209 void ChromotingClient::Initialize() { |
| 218 if (!message_loop()->BelongsToCurrentThread()) { | 210 DCHECK(task_runner()->BelongsToCurrentThread()); |
| 219 thread_proxy_.PostTask(FROM_HERE, base::Bind( | |
| 220 &ChromotingClient::Initialize, base::Unretained(this))); | |
| 221 return; | |
| 222 } | |
| 223 | 211 |
| 224 // Initialize the decoder. | 212 // Initialize the decoder. |
| 225 rectangle_decoder_->Initialize(connection_->config()); | 213 rectangle_decoder_->Initialize(connection_->config()); |
| 226 } | 214 } |
| 227 | 215 |
| 228 } // namespace remoting | 216 } // namespace remoting |
| OLD | NEW |