Chromium Code Reviews| Index: remoting/host/screen_recorder.cc |
| diff --git a/remoting/host/screen_recorder.cc b/remoting/host/screen_recorder.cc |
| index cf3417ce4129cc102007c17ec40f1244bbfd312c..193bb1c63d03461ce72e93f5a73100b14bff6e8c 100644 |
| --- a/remoting/host/screen_recorder.cc |
| +++ b/remoting/host/screen_recorder.cc |
| @@ -46,6 +46,7 @@ ScreenRecorder::ScreenRecorder( |
| capturer_(capturer), |
| encoder_(encoder), |
| started_(false), |
| + network_stopped_(false), |
| recordings_(0), |
| frame_skipped_(false), |
| max_rate_(kDefaultCaptureRate) { |
| @@ -65,9 +66,9 @@ void ScreenRecorder::Start() { |
| FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStart)); |
| } |
| -void ScreenRecorder::Pause() { |
| +void ScreenRecorder::Stop(Task* task) { |
| capture_loop_->PostTask( |
| - FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoPause)); |
| + FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStop, task)); |
| } |
| void ScreenRecorder::SetMaxRate(double rate) { |
| @@ -116,7 +117,6 @@ Encoder* ScreenRecorder::encoder() { |
| void ScreenRecorder::DoStart() { |
| DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| - DCHECK(!started_); |
| if (started_) { |
| NOTREACHED() << "Record session already started."; |
| @@ -130,7 +130,7 @@ void ScreenRecorder::DoStart() { |
| DoCapture(); |
| } |
| -void ScreenRecorder::DoPause() { |
| +void ScreenRecorder::DoStop(Task* task) { |
| DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| if (!started_) { |
| @@ -140,6 +140,28 @@ void ScreenRecorder::DoPause() { |
| capture_timer_.Stop(); |
| started_ = false; |
| + |
| + DCHECK_GE(recordings_, 0); |
| + if (recordings_) { |
| + network_loop_->PostTask( |
| + FROM_HERE, |
| + NewTracedMethod(this, &ScreenRecorder::DoStopOnNetworkThread, task)); |
| + return; |
| + } |
| + |
| + if (task) { |
|
Sergey Ulanov
2011/01/20 19:14:17
Call DoCompleteStop()?
Alpha Left Google
2011/01/20 19:32:08
Done.
|
| + task->Run(); |
| + delete task; |
| + } |
| +} |
| + |
| +void ScreenRecorder::DoCompleteStop(Task* task) { |
| + DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| + |
| + if (task) { |
| + task->Run(); |
| + delete task; |
| + } |
| } |
| void ScreenRecorder::DoSetMaxRate(double max_rate) { |
| @@ -184,6 +206,7 @@ void ScreenRecorder::DoCapture() { |
| // At this point we are going to perform one capture so save the current time. |
| ++recordings_; |
| + DCHECK_LE(recordings_, kMaxRecordings); |
| // And finally perform one capture. |
| capturer()->CaptureInvalidRects( |
| @@ -192,21 +215,27 @@ void ScreenRecorder::DoCapture() { |
| void ScreenRecorder::CaptureDoneCallback( |
| scoped_refptr<CaptureData> capture_data) { |
| - // TODO(hclam): There is a bug if the capturer doesn't produce any dirty |
| - // rects. |
| DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| + |
| + if (!started_) |
| + return; |
| + |
| TraceContext::tracer()->PrintString("Capture Done"); |
| encode_loop_->PostTask( |
| FROM_HERE, |
| NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data)); |
| } |
| -void ScreenRecorder::DoFinishSend() { |
| +void ScreenRecorder::DoFinishOneRecording() { |
| DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| + if (!started_) |
| + return; |
| + |
| // Decrement the number of recording in process since we have completed |
| // one cycle. |
| --recordings_; |
| + DCHECK_GE(recordings_, 0); |
| // Try to do a capture again. Note that the following method may do nothing |
| // if it is too early to perform a capture. |
| @@ -222,14 +251,23 @@ void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { |
| bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0; |
| + if (network_stopped_) { |
| + delete packet; |
| + return; |
| + } |
| + |
| for (ConnectionToClientList::const_iterator i = connections_.begin(); |
| i < connections_.end(); ++i) { |
| Task* done_task = NULL; |
| - // Call OnFrameSent() only for the last packet in the first connection. |
| + // Call FrameSentCallback() only for the last packet in the first |
| + // connection. |
| if (last && i == connections_.begin()) { |
| - done_task = NewTracedMethod(this, &ScreenRecorder::OnFrameSent, packet); |
| + done_task = NewTracedMethod(this, &ScreenRecorder::FrameSentCallback, |
| + packet); |
| } else { |
| + // TODO(hclam): Fix this code since it causes multiple deletion if there's |
| + // more than one connection. |
|
Sergey Ulanov
2011/01/20 19:14:17
I think we should just remove support for parallel
Alpha Left Google
2011/01/20 19:24:18
I'd leave the decision later, not really related t
|
| done_task = new DeleteTask<VideoPacket>(packet); |
| } |
| @@ -239,10 +277,14 @@ void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { |
| TraceContext::tracer()->PrintString("DoSendVideoPacket done"); |
| } |
| -void ScreenRecorder::OnFrameSent(VideoPacket* packet) { |
| +void ScreenRecorder::FrameSentCallback(VideoPacket* packet) { |
| delete packet; |
| + |
| + if (network_stopped_) |
|
Sergey Ulanov
2011/01/20 19:14:17
Do we really need network_stopped_? It should be s
Alpha Left Google
2011/01/20 19:24:18
The problem that needs network_stopped_ here is th
|
| + return; |
| + |
| capture_loop_->PostTask( |
| - FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); |
| + FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording)); |
| } |
| void ScreenRecorder::DoAddConnection( |
| @@ -272,6 +314,22 @@ void ScreenRecorder::DoRemoveAllClients() { |
| connections_.clear(); |
| } |
| +void ScreenRecorder::DoStopOnNetworkThread(Task* task) { |
| + DCHECK_EQ(network_loop_, MessageLoop::current()); |
| + |
| + // There could be tasks on the network thread when this method is being |
| + // executed. By setting the flag we'll not post anymore tasks from network |
| + // thread. |
| + // |
| + // After that a task is posted on encode thread to continue the stop |
| + // sequence. |
| + network_stopped_ = true; |
| + |
| + encode_loop_->PostTask( |
| + FROM_HERE, |
| + NewTracedMethod(this, &ScreenRecorder::DoStopOnEncodeThread, task)); |
| +} |
| + |
| // Encoder thread -------------------------------------------------------------- |
| void ScreenRecorder::DoEncode( |
| @@ -282,19 +340,31 @@ void ScreenRecorder::DoEncode( |
| // Early out if there's nothing to encode. |
| if (!capture_data->dirty_rects().size()) { |
| capture_loop_->PostTask( |
| - FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); |
| + FROM_HERE, |
| + NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording)); |
| return; |
| } |
| - // TODO(hclam): Enable |force_refresh| if a new connection was |
| - // added. |
| + // TODO(hclam): Invalid the full screen if there is a new connection added. |
|
Sergey Ulanov
2011/01/20 19:14:17
Invalidate
|
| TraceContext::tracer()->PrintString("Encode start"); |
| - encoder()->Encode(capture_data, false, |
| - NewCallback(this, &ScreenRecorder::EncodeDataAvailableTask)); |
| + encoder()->Encode( |
| + capture_data, false, |
| + NewCallback(this, &ScreenRecorder::EncodedDataAvailableCallback)); |
| TraceContext::tracer()->PrintString("Encode Done"); |
| } |
| -void ScreenRecorder::EncodeDataAvailableTask(VideoPacket* packet) { |
| +void ScreenRecorder::DoStopOnEncodeThread(Task* task) { |
| + DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| + |
| + // When this method is being executed there are no more tasks on encode thread |
| + // for this object. We can then post a task to capture thread to finish the |
| + // stop sequence. |
| + capture_loop_->PostTask( |
| + FROM_HERE, |
| + NewTracedMethod(this, &ScreenRecorder::DoCompleteStop, task)); |
| +} |
| + |
| +void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) { |
| DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| network_loop_->PostTask( |