| 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 |