OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/host/session_manager.h" | 5 #include "remoting/host/session_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/scoped_ptr.h" | 10 #include "base/scoped_ptr.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 FROM_HERE, | 132 FROM_HERE, |
133 NewRunnableMethod(this, &SessionManager::DoGetInitInfo, client)); | 133 NewRunnableMethod(this, &SessionManager::DoGetInitInfo, client)); |
134 } | 134 } |
135 | 135 |
136 void SessionManager::RemoveClient(scoped_refptr<ClientConnection> client) { | 136 void SessionManager::RemoveClient(scoped_refptr<ClientConnection> client) { |
137 network_loop_->PostTask( | 137 network_loop_->PostTask( |
138 FROM_HERE, | 138 FROM_HERE, |
139 NewRunnableMethod(this, &SessionManager::DoRemoveClient, client)); | 139 NewRunnableMethod(this, &SessionManager::DoRemoveClient, client)); |
140 } | 140 } |
141 | 141 |
| 142 void SessionManager::RemoveAllClients() { |
| 143 network_loop_->PostTask( |
| 144 FROM_HERE, |
| 145 NewRunnableMethod(this, &SessionManager::DoRemoveAllClients)); |
| 146 } |
| 147 |
142 void SessionManager::DoCapture() { | 148 void SessionManager::DoCapture() { |
143 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 149 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
144 | 150 |
145 // Make sure we have at most two oustanding recordings. We can simply return | 151 // Make sure we have at most two oustanding recordings. We can simply return |
146 // if we can't make a capture now, the next capture will be started by the | 152 // if we can't make a capture now, the next capture will be started by the |
147 // end of an encode operation. | 153 // end of an encode operation. |
148 if (recordings_ >= 2 || !started_) | 154 if (recordings_ >= 2 || !started_) |
149 return; | 155 return; |
150 | 156 |
151 base::Time now = base::Time::Now(); | 157 base::Time now = base::Time::Now(); |
152 base::TimeDelta interval = base::TimeDelta::FromMilliseconds( | 158 base::TimeDelta interval = base::TimeDelta::FromMilliseconds( |
153 static_cast<int>(base::Time::kMillisecondsPerSecond / rate_)); | 159 static_cast<int>(base::Time::kMillisecondsPerSecond / rate_)); |
154 base::TimeDelta elapsed = now - last_capture_time_; | 160 base::TimeDelta elapsed = now - last_capture_time_; |
155 | 161 |
156 // If this method is called sonner than the required interval we return | 162 // If this method is called sonner than the required interval we return |
157 // immediately | 163 // immediately |
158 if (elapsed < interval) | 164 if (elapsed < interval) |
159 return; | 165 return; |
160 | 166 |
161 // At this point we are going to perform one capture so save the current time. | 167 // At this point we are going to perform one capture so save the current time. |
162 last_capture_time_ = now; | 168 last_capture_time_ = now; |
163 ++recordings_; | 169 ++recordings_; |
164 | 170 |
165 // Before we actually do a capture, schedule the next one. | 171 // Before we actually do a capture, schedule the next one. |
166 ScheduleNextCapture(); | 172 ScheduleNextCapture(); |
167 | 173 |
168 // And finally perform one capture. | 174 // And finally perform one capture. |
169 DCHECK(capturer_.get()); | 175 capturer()->CaptureDirtyRects( |
170 capturer_->CaptureDirtyRects( | |
171 NewRunnableMethod(this, &SessionManager::CaptureDoneTask)); | 176 NewRunnableMethod(this, &SessionManager::CaptureDoneTask)); |
172 } | 177 } |
173 | 178 |
174 void SessionManager::DoFinishEncode() { | 179 void SessionManager::DoFinishEncode() { |
175 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 180 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
176 | 181 |
177 // Decrement the number of recording in process since we have completed | 182 // Decrement the number of recording in process since we have completed |
178 // one cycle. | 183 // one cycle. |
179 --recordings_; | 184 --recordings_; |
180 | 185 |
181 // Try to do a capture again. Note that the following method may do nothing | 186 // Try to do a capture again. Note that the following method may do nothing |
182 // if it is too early to perform a capture. | 187 // if it is too early to perform a capture. |
183 if (rate_ > 0) | 188 if (rate_ > 0) |
184 DoCapture(); | 189 DoCapture(); |
185 } | 190 } |
186 | 191 |
187 void SessionManager::DoEncode(const CaptureData *capture_data) { | 192 void SessionManager::DoEncode(const CaptureData *capture_data) { |
188 // Take ownership of capture_data. | 193 // Take ownership of capture_data. |
189 scoped_ptr<const CaptureData> capture_data_owner(capture_data); | 194 scoped_ptr<const CaptureData> capture_data_owner(capture_data); |
190 | 195 |
191 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 196 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
192 | 197 |
193 DCHECK(encoder_.get()); | |
194 | |
195 // TODO(hclam): Enable |force_refresh| if a new client was | 198 // TODO(hclam): Enable |force_refresh| if a new client was |
196 // added. | 199 // added. |
197 encoder_->SetSize(capture_data->width_, capture_data->height_); | 200 encoder()->SetSize(capture_data->width_, capture_data->height_); |
198 encoder_->SetPixelFormat(capture_data->pixel_format_); | 201 encoder()->SetPixelFormat(capture_data->pixel_format_); |
199 encoder_->Encode( | 202 encoder()->Encode( |
200 capture_data->dirty_rects_, | 203 capture_data->dirty_rects_, |
201 capture_data->data_, | 204 capture_data->data_, |
202 capture_data->data_strides_, | 205 capture_data->data_strides_, |
203 false, | 206 false, |
204 NewCallback(this, &SessionManager::EncodeDataAvailableTask)); | 207 NewCallback(this, &SessionManager::EncodeDataAvailableTask)); |
205 } | 208 } |
206 | 209 |
207 void SessionManager::DoSendUpdate(const UpdateStreamPacketHeader* header, | 210 void SessionManager::DoSendUpdate(const UpdateStreamPacketHeader* header, |
208 const scoped_refptr<media::DataBuffer> data, | 211 const scoped_refptr<media::DataBuffer> data, |
209 Encoder::EncodingState state) { | 212 Encoder::EncodingState state) { |
(...skipping 22 matching lines...) Expand all Loading... |
232 client->SendInitClientMessage(width, height); | 235 client->SendInitClientMessage(width, height); |
233 } | 236 } |
234 | 237 |
235 void SessionManager::DoGetInitInfo(scoped_refptr<ClientConnection> client) { | 238 void SessionManager::DoGetInitInfo(scoped_refptr<ClientConnection> client) { |
236 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 239 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
237 | 240 |
238 // Sends the init message to the cleint. | 241 // Sends the init message to the cleint. |
239 network_loop_->PostTask( | 242 network_loop_->PostTask( |
240 FROM_HERE, | 243 FROM_HERE, |
241 NewRunnableMethod(this, &SessionManager::DoSendInit, client, | 244 NewRunnableMethod(this, &SessionManager::DoSendInit, client, |
242 capturer_->GetWidth(), capturer_->GetHeight())); | 245 capturer()->GetWidth(), capturer()->GetHeight())); |
243 | 246 |
244 // And then add the client to the list so it can receive update stream. | 247 // And then add the client to the list so it can receive update stream. |
245 // It is important we do so in such order or the client will receive | 248 // It is important we do so in such order or the client will receive |
246 // update stream before init message. | 249 // update stream before init message. |
247 network_loop_->PostTask( | 250 network_loop_->PostTask( |
248 FROM_HERE, | 251 FROM_HERE, |
249 NewRunnableMethod(this, &SessionManager::DoAddClient, client)); | 252 NewRunnableMethod(this, &SessionManager::DoAddClient, client)); |
250 } | 253 } |
251 | 254 |
252 void SessionManager::DoSetRate(double rate) { | 255 void SessionManager::DoSetRate(double rate) { |
(...skipping 28 matching lines...) Expand all Loading... |
281 // TODO(hclam): Force a full frame for next encode. | 284 // TODO(hclam): Force a full frame for next encode. |
282 clients_.push_back(client); | 285 clients_.push_back(client); |
283 } | 286 } |
284 | 287 |
285 void SessionManager::DoRemoveClient(scoped_refptr<ClientConnection> client) { | 288 void SessionManager::DoRemoveClient(scoped_refptr<ClientConnection> client) { |
286 DCHECK_EQ(network_loop_, MessageLoop::current()); | 289 DCHECK_EQ(network_loop_, MessageLoop::current()); |
287 | 290 |
288 // TODO(hclam): Is it correct to do to a scoped_refptr? | 291 // TODO(hclam): Is it correct to do to a scoped_refptr? |
289 ClientConnectionList::iterator it | 292 ClientConnectionList::iterator it |
290 = std::find(clients_.begin(), clients_.end(), client); | 293 = std::find(clients_.begin(), clients_.end(), client); |
291 if (it != clients_.end()) | 294 if (it != clients_.end()) { |
292 clients_.erase(it); | 295 clients_.erase(it); |
| 296 } |
| 297 } |
| 298 |
| 299 void SessionManager::DoRemoveAllClients() { |
| 300 DCHECK_EQ(network_loop_, MessageLoop::current()); |
| 301 |
| 302 // Clear the list of clients. |
| 303 clients_.clear(); |
293 } | 304 } |
294 | 305 |
295 void SessionManager::DoRateControl() { | 306 void SessionManager::DoRateControl() { |
296 DCHECK_EQ(network_loop_, MessageLoop::current()); | 307 DCHECK_EQ(network_loop_, MessageLoop::current()); |
297 | 308 |
298 // If we have been paused then shutdown the rate regulation loop. | 309 // If we have been paused then shutdown the rate regulation loop. |
299 if (!rate_control_started_) | 310 if (!rate_control_started_) |
300 return; | 311 return; |
301 | 312 |
302 int max_pending_update_streams = 0; | 313 int max_pending_update_streams = 0; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 NewRunnableMethod(this, &SessionManager::DoRateControl), | 358 NewRunnableMethod(this, &SessionManager::DoRateControl), |
348 kRateControlInterval.InMilliseconds()); | 359 kRateControlInterval.InMilliseconds()); |
349 } | 360 } |
350 | 361 |
351 void SessionManager::CaptureDoneTask() { | 362 void SessionManager::CaptureDoneTask() { |
352 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 363 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
353 | 364 |
354 scoped_ptr<CaptureData> data(new CaptureData); | 365 scoped_ptr<CaptureData> data(new CaptureData); |
355 | 366 |
356 // Save results of the capture. | 367 // Save results of the capture. |
357 capturer_->GetData(data->data_); | 368 capturer()->GetData(data->data_); |
358 capturer_->GetDataStride(data->data_strides_); | 369 capturer()->GetDataStride(data->data_strides_); |
359 capturer_->GetDirtyRects(&data->dirty_rects_); | 370 capturer()->GetDirtyRects(&data->dirty_rects_); |
360 data->pixel_format_ = capturer_->GetPixelFormat(); | 371 data->pixel_format_ = capturer()->GetPixelFormat(); |
361 data->width_ = capturer_->GetWidth(); | 372 data->width_ = capturer()->GetWidth(); |
362 data->height_ = capturer_->GetHeight(); | 373 data->height_ = capturer()->GetHeight(); |
363 | 374 |
364 encode_loop_->PostTask( | 375 encode_loop_->PostTask( |
365 FROM_HERE, | 376 FROM_HERE, |
366 NewRunnableMethod(this, &SessionManager::DoEncode, data.release())); | 377 NewRunnableMethod(this, &SessionManager::DoEncode, data.release())); |
367 } | 378 } |
368 | 379 |
369 void SessionManager::EncodeDataAvailableTask( | 380 void SessionManager::EncodeDataAvailableTask( |
370 const UpdateStreamPacketHeader *header, | 381 const UpdateStreamPacketHeader *header, |
371 const scoped_refptr<media::DataBuffer>& data, | 382 const scoped_refptr<media::DataBuffer>& data, |
372 Encoder::EncodingState state) { | 383 Encoder::EncodingState state) { |
373 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 384 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
374 | 385 |
375 // Before a new encode task starts, notify clients a new update | 386 // Before a new encode task starts, notify clients a new update |
376 // stream is coming. | 387 // stream is coming. |
377 // Notify this will keep a reference to the DataBuffer in the | 388 // Notify this will keep a reference to the DataBuffer in the |
378 // task. The ownership will eventually pass to the ClientConnections. | 389 // task. The ownership will eventually pass to the ClientConnections. |
379 network_loop_->PostTask( | 390 network_loop_->PostTask( |
380 FROM_HERE, | 391 FROM_HERE, |
381 NewRunnableMethod(this, | 392 NewRunnableMethod(this, |
382 &SessionManager::DoSendUpdate, | 393 &SessionManager::DoSendUpdate, |
383 header, | 394 header, |
384 data, | 395 data, |
385 state)); | 396 state)); |
386 | 397 |
387 if (state == Encoder::EncodingEnded) { | 398 if (state & Encoder::EncodingEnded) { |
388 capture_loop_->PostTask( | 399 capture_loop_->PostTask( |
389 FROM_HERE, NewRunnableMethod(this, &SessionManager::DoFinishEncode)); | 400 FROM_HERE, NewRunnableMethod(this, &SessionManager::DoFinishEncode)); |
390 } | 401 } |
391 } | 402 } |
392 | 403 |
| 404 Capturer* SessionManager::capturer() { |
| 405 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 406 return capturer_.get(); |
| 407 } |
| 408 |
| 409 Encoder* SessionManager::encoder() { |
| 410 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 411 return encoder_.get(); |
| 412 } |
| 413 |
393 } // namespace remoting | 414 } // namespace remoting |
OLD | NEW |