| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/video_frame_recorder.h" | 5 #include "remoting/host/video_frame_recorder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/single_thread_task_runner.h" | 9 #include "base/single_thread_task_runner.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 public: | 27 public: |
| 28 RecordingVideoEncoder(scoped_ptr<VideoEncoder> encoder, | 28 RecordingVideoEncoder(scoped_ptr<VideoEncoder> encoder, |
| 29 scoped_refptr<base::TaskRunner> recorder_task_runner, | 29 scoped_refptr<base::TaskRunner> recorder_task_runner, |
| 30 base::WeakPtr<VideoFrameRecorder> recorder) | 30 base::WeakPtr<VideoFrameRecorder> recorder) |
| 31 : encoder_(encoder.Pass()), | 31 : encoder_(encoder.Pass()), |
| 32 recorder_task_runner_(recorder_task_runner), | 32 recorder_task_runner_(recorder_task_runner), |
| 33 recorder_(recorder), | 33 recorder_(recorder), |
| 34 enable_recording_(false), | 34 enable_recording_(false), |
| 35 weak_factory_(this) { | 35 weak_factory_(this) { |
| 36 DCHECK(encoder_); | 36 DCHECK(encoder_); |
| 37 DCHECK(recorder_task_runner_); | 37 DCHECK(recorder_task_runner_.get()); |
| 38 } | 38 } |
| 39 | 39 |
| 40 base::WeakPtr<RecordingVideoEncoder> AsWeakPtr() { | 40 base::WeakPtr<RecordingVideoEncoder> AsWeakPtr() { |
| 41 return weak_factory_.GetWeakPtr(); | 41 return weak_factory_.GetWeakPtr(); |
| 42 } | 42 } |
| 43 | 43 |
| 44 void SetEnableRecording(bool enable_recording) { | 44 void SetEnableRecording(bool enable_recording) { |
| 45 DCHECK(!encoder_task_runner_ || | 45 DCHECK(!encoder_task_runner_.get() || |
| 46 encoder_task_runner_->BelongsToCurrentThread()); | 46 encoder_task_runner_->BelongsToCurrentThread()); |
| 47 enable_recording_ = enable_recording; | 47 enable_recording_ = enable_recording; |
| 48 } | 48 } |
| 49 | 49 |
| 50 // remoting::VideoEncoder interface. | 50 // remoting::VideoEncoder interface. |
| 51 virtual void SetLosslessEncode(bool want_lossless) OVERRIDE { | 51 virtual void SetLosslessEncode(bool want_lossless) OVERRIDE { |
| 52 encoder_->SetLosslessEncode(want_lossless); | 52 encoder_->SetLosslessEncode(want_lossless); |
| 53 } | 53 } |
| 54 virtual void SetLosslessColor(bool want_lossless) OVERRIDE { | 54 virtual void SetLosslessColor(bool want_lossless) OVERRIDE { |
| 55 encoder_->SetLosslessColor(want_lossless); | 55 encoder_->SetLosslessColor(want_lossless); |
| 56 } | 56 } |
| 57 virtual scoped_ptr<VideoPacket> Encode( | 57 virtual scoped_ptr<VideoPacket> Encode( |
| 58 const webrtc::DesktopFrame& frame) OVERRIDE { | 58 const webrtc::DesktopFrame& frame) OVERRIDE { |
| 59 // If this is the first Encode() then store the TaskRunner and inform the | 59 // If this is the first Encode() then store the TaskRunner and inform the |
| 60 // VideoFrameRecorder so it can post SetEnableRecording() on it. | 60 // VideoFrameRecorder so it can post SetEnableRecording() on it. |
| 61 if (!encoder_task_runner_) { | 61 if (!encoder_task_runner_.get()) { |
| 62 encoder_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 62 encoder_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 63 recorder_task_runner_->PostTask(FROM_HERE, | 63 recorder_task_runner_->PostTask(FROM_HERE, |
| 64 base::Bind(&VideoFrameRecorder::SetEncoderTaskRunner, | 64 base::Bind(&VideoFrameRecorder::SetEncoderTaskRunner, |
| 65 recorder_, | 65 recorder_, |
| 66 encoder_task_runner_)); | 66 encoder_task_runner_)); |
| 67 } | 67 } |
| 68 | 68 |
| 69 DCHECK(encoder_task_runner_->BelongsToCurrentThread()); | 69 DCHECK(encoder_task_runner_->BelongsToCurrentThread()); |
| 70 | 70 |
| 71 if (enable_recording_) { | 71 if (enable_recording_) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 enable_recording_(false), | 105 enable_recording_(false), |
| 106 weak_factory_(this) { | 106 weak_factory_(this) { |
| 107 } | 107 } |
| 108 | 108 |
| 109 VideoFrameRecorder::~VideoFrameRecorder() { | 109 VideoFrameRecorder::~VideoFrameRecorder() { |
| 110 DetachVideoEncoderWrapper(); | 110 DetachVideoEncoderWrapper(); |
| 111 } | 111 } |
| 112 | 112 |
| 113 scoped_ptr<VideoEncoder> VideoFrameRecorder::WrapVideoEncoder( | 113 scoped_ptr<VideoEncoder> VideoFrameRecorder::WrapVideoEncoder( |
| 114 scoped_ptr<VideoEncoder> encoder) { | 114 scoped_ptr<VideoEncoder> encoder) { |
| 115 DCHECK(!encoder_task_runner_); | 115 DCHECK(!encoder_task_runner_.get()); |
| 116 DCHECK(!caller_task_runner_); | 116 DCHECK(!caller_task_runner_.get()); |
| 117 caller_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 117 caller_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 118 | 118 |
| 119 scoped_ptr<RecordingVideoEncoder> recording_encoder( | 119 scoped_ptr<RecordingVideoEncoder> recording_encoder( |
| 120 new RecordingVideoEncoder(encoder.Pass(), | 120 new RecordingVideoEncoder(encoder.Pass(), |
| 121 caller_task_runner_, | 121 caller_task_runner_, |
| 122 weak_factory_.GetWeakPtr())); | 122 weak_factory_.GetWeakPtr())); |
| 123 recording_encoder_ = recording_encoder->AsWeakPtr(); | 123 recording_encoder_ = recording_encoder->AsWeakPtr(); |
| 124 | 124 |
| 125 return recording_encoder.PassAs<VideoEncoder>(); | 125 return recording_encoder.PassAs<VideoEncoder>(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 void VideoFrameRecorder::DetachVideoEncoderWrapper() { | 128 void VideoFrameRecorder::DetachVideoEncoderWrapper() { |
| 129 DCHECK(!caller_task_runner_ || caller_task_runner_->BelongsToCurrentThread()); | 129 DCHECK(!caller_task_runner_.get() || |
| 130 caller_task_runner_->BelongsToCurrentThread()); |
| 130 | 131 |
| 131 // Immediately detach the wrapper from this recorder. | 132 // Immediately detach the wrapper from this recorder. |
| 132 weak_factory_.InvalidateWeakPtrs(); | 133 weak_factory_.InvalidateWeakPtrs(); |
| 133 | 134 |
| 134 // Clean up any pending recorded frames. | 135 // Clean up any pending recorded frames. |
| 135 STLDeleteElements(&recorded_frames_); | 136 STLDeleteElements(&recorded_frames_); |
| 136 content_bytes_ = 0; | 137 content_bytes_ = 0; |
| 137 | 138 |
| 138 // Tell the wrapper to stop recording and posting frames to us. | 139 // Tell the wrapper to stop recording and posting frames to us. |
| 139 if (encoder_task_runner_) { | 140 if (encoder_task_runner_.get()) { |
| 140 encoder_task_runner_->PostTask(FROM_HERE, | 141 encoder_task_runner_->PostTask(FROM_HERE, |
| 141 base::Bind(&RecordingVideoEncoder::SetEnableRecording, | 142 base::Bind(&RecordingVideoEncoder::SetEnableRecording, |
| 142 recording_encoder_, false)); | 143 recording_encoder_, false)); |
| 143 } | 144 } |
| 144 | 145 |
| 145 // Detach this recorder from the calling and encode threads. | 146 // Detach this recorder from the calling and encode threads. |
| 146 caller_task_runner_ = NULL; | 147 caller_task_runner_ = NULL; |
| 147 encoder_task_runner_ = NULL; | 148 encoder_task_runner_ = NULL; |
| 148 } | 149 } |
| 149 | 150 |
| 150 void VideoFrameRecorder::SetEnableRecording(bool enable_recording) { | 151 void VideoFrameRecorder::SetEnableRecording(bool enable_recording) { |
| 151 DCHECK(!caller_task_runner_ || caller_task_runner_->BelongsToCurrentThread()); | 152 DCHECK(!caller_task_runner_.get() || |
| 153 caller_task_runner_->BelongsToCurrentThread()); |
| 152 | 154 |
| 153 if (enable_recording_ == enable_recording) { | 155 if (enable_recording_ == enable_recording) { |
| 154 return; | 156 return; |
| 155 } | 157 } |
| 156 enable_recording_ = enable_recording; | 158 enable_recording_ = enable_recording; |
| 157 | 159 |
| 158 if (encoder_task_runner_) { | 160 if (encoder_task_runner_.get()) { |
| 159 encoder_task_runner_->PostTask(FROM_HERE, | 161 encoder_task_runner_->PostTask(FROM_HERE, |
| 160 base::Bind(&RecordingVideoEncoder::SetEnableRecording, | 162 base::Bind(&RecordingVideoEncoder::SetEnableRecording, |
| 161 recording_encoder_, | 163 recording_encoder_, |
| 162 enable_recording_)); | 164 enable_recording_)); |
| 163 } | 165 } |
| 164 } | 166 } |
| 165 | 167 |
| 166 void VideoFrameRecorder::SetMaxContentBytes(int64_t max_content_bytes) { | 168 void VideoFrameRecorder::SetMaxContentBytes(int64_t max_content_bytes) { |
| 167 DCHECK(!caller_task_runner_ || caller_task_runner_->BelongsToCurrentThread()); | 169 DCHECK(!caller_task_runner_.get() || |
| 170 caller_task_runner_->BelongsToCurrentThread()); |
| 168 DCHECK_GE(max_content_bytes, 0); | 171 DCHECK_GE(max_content_bytes, 0); |
| 169 | 172 |
| 170 max_content_bytes_ = max_content_bytes; | 173 max_content_bytes_ = max_content_bytes; |
| 171 } | 174 } |
| 172 | 175 |
| 173 scoped_ptr<webrtc::DesktopFrame> VideoFrameRecorder::NextFrame() { | 176 scoped_ptr<webrtc::DesktopFrame> VideoFrameRecorder::NextFrame() { |
| 174 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 177 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 175 | 178 |
| 176 scoped_ptr<webrtc::DesktopFrame> frame; | 179 scoped_ptr<webrtc::DesktopFrame> frame; |
| 177 if (!recorded_frames_.empty()) { | 180 if (!recorded_frames_.empty()) { |
| 178 frame.reset(recorded_frames_.front()); | 181 frame.reset(recorded_frames_.front()); |
| 179 recorded_frames_.pop_front(); | 182 recorded_frames_.pop_front(); |
| 180 content_bytes_ -= FrameContentSize(frame.get()); | 183 content_bytes_ -= FrameContentSize(frame.get()); |
| 181 DCHECK_GE(content_bytes_, 0); | 184 DCHECK_GE(content_bytes_, 0); |
| 182 } | 185 } |
| 183 | 186 |
| 184 return frame.Pass(); | 187 return frame.Pass(); |
| 185 } | 188 } |
| 186 | 189 |
| 187 void VideoFrameRecorder::SetEncoderTaskRunner( | 190 void VideoFrameRecorder::SetEncoderTaskRunner( |
| 188 scoped_refptr<base::TaskRunner> task_runner) { | 191 scoped_refptr<base::TaskRunner> task_runner) { |
| 189 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 192 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 190 DCHECK(!encoder_task_runner_); | 193 DCHECK(!encoder_task_runner_.get()); |
| 191 DCHECK(task_runner); | 194 DCHECK(task_runner.get()); |
| 192 | 195 |
| 193 encoder_task_runner_ = task_runner; | 196 encoder_task_runner_ = task_runner; |
| 194 | 197 |
| 195 // If the caller already enabled recording, inform the recording encoder. | 198 // If the caller already enabled recording, inform the recording encoder. |
| 196 if (enable_recording_ && encoder_task_runner_) { | 199 if (enable_recording_ && encoder_task_runner_.get()) { |
| 197 encoder_task_runner_->PostTask(FROM_HERE, | 200 encoder_task_runner_->PostTask(FROM_HERE, |
| 198 base::Bind(&RecordingVideoEncoder::SetEnableRecording, | 201 base::Bind(&RecordingVideoEncoder::SetEnableRecording, |
| 199 recording_encoder_, | 202 recording_encoder_, |
| 200 enable_recording_)); | 203 enable_recording_)); |
| 201 } | 204 } |
| 202 } | 205 } |
| 203 | 206 |
| 204 void VideoFrameRecorder::RecordFrame(scoped_ptr<webrtc::DesktopFrame> frame) { | 207 void VideoFrameRecorder::RecordFrame(scoped_ptr<webrtc::DesktopFrame> frame) { |
| 205 DCHECK(caller_task_runner_->BelongsToCurrentThread()); | 208 DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 206 | 209 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 220 if (content_bytes_ + frame_bytes > max_content_bytes_) { | 223 if (content_bytes_ + frame_bytes > max_content_bytes_) { |
| 221 return; | 224 return; |
| 222 } | 225 } |
| 223 | 226 |
| 224 // Store the frame and update the content byte count. | 227 // Store the frame and update the content byte count. |
| 225 recorded_frames_.push_back(frame.release()); | 228 recorded_frames_.push_back(frame.release()); |
| 226 content_bytes_ += frame_bytes; | 229 content_bytes_ += frame_bytes; |
| 227 } | 230 } |
| 228 | 231 |
| 229 } // namespace remoting | 232 } // namespace remoting |
| OLD | NEW |