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/rectangle_update_decoder.h" | 5 #include "remoting/client/software_video_renderer.h" |
| 6 |
| 7 #include <list> |
6 | 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/callback.h" | 10 #include "base/callback.h" |
9 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
10 #include "base/location.h" | 12 #include "base/location.h" |
11 #include "base/logging.h" | 13 #include "base/logging.h" |
12 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
13 #include "remoting/base/util.h" | 15 #include "remoting/base/util.h" |
14 #include "remoting/client/frame_consumer.h" | 16 #include "remoting/client/frame_consumer.h" |
15 #include "remoting/codec/video_decoder.h" | 17 #include "remoting/codec/video_decoder.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 } | 69 } |
68 | 70 |
69 virtual const webrtc::DesktopRegion* GetImageShape() OVERRIDE { | 71 virtual const webrtc::DesktopRegion* GetImageShape() OVERRIDE { |
70 return parent_->GetImageShape(); | 72 return parent_->GetImageShape(); |
71 } | 73 } |
72 | 74 |
73 private: | 75 private: |
74 scoped_ptr<VideoDecoder> parent_; | 76 scoped_ptr<VideoDecoder> parent_; |
75 }; | 77 }; |
76 | 78 |
77 RectangleUpdateDecoder::RectangleUpdateDecoder( | 79 class SoftwareVideoRenderer::Core { |
| 80 public: |
| 81 Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 82 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
| 83 scoped_refptr<FrameConsumerProxy> consumer); |
| 84 ~Core(); |
| 85 |
| 86 void Initialize(const protocol::SessionConfig& config); |
| 87 void DrawBuffer(webrtc::DesktopFrame* buffer); |
| 88 void InvalidateRegion(const webrtc::DesktopRegion& region); |
| 89 void RequestReturnBuffers(const base::Closure& done); |
| 90 void SetOutputSizeAndClip( |
| 91 const webrtc::DesktopSize& view_size, |
| 92 const webrtc::DesktopRect& clip_area); |
| 93 |
| 94 // Decodes the contents of |packet|. DecodePacket may keep a reference to |
| 95 // |packet| so the |packet| must remain alive and valid until |done| is |
| 96 // executed. |
| 97 void DecodePacket(scoped_ptr<VideoPacket> packet, const base::Closure& done); |
| 98 |
| 99 private: |
| 100 // Paints the invalidated region to the next available buffer and returns it |
| 101 // to the consumer. |
| 102 void SchedulePaint(); |
| 103 void DoPaint(); |
| 104 |
| 105 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
| 106 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_; |
| 107 scoped_refptr<FrameConsumerProxy> consumer_; |
| 108 scoped_ptr<VideoDecoder> decoder_; |
| 109 |
| 110 // Remote screen size in pixels. |
| 111 webrtc::DesktopSize source_size_; |
| 112 |
| 113 // Vertical and horizontal DPI of the remote screen. |
| 114 webrtc::DesktopVector source_dpi_; |
| 115 |
| 116 // The current dimensions of the frame consumer view. |
| 117 webrtc::DesktopSize view_size_; |
| 118 webrtc::DesktopRect clip_area_; |
| 119 |
| 120 // The drawing buffers supplied by the frame consumer. |
| 121 std::list<webrtc::DesktopFrame*> buffers_; |
| 122 |
| 123 // Flag used to coalesce runs of SchedulePaint()s into a single DoPaint(). |
| 124 bool paint_scheduled_; |
| 125 |
| 126 base::WeakPtrFactory<Core> weak_factory_; |
| 127 }; |
| 128 |
| 129 SoftwareVideoRenderer::Core::Core( |
78 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 130 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
79 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, | 131 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
80 scoped_refptr<FrameConsumerProxy> consumer) | 132 scoped_refptr<FrameConsumerProxy> consumer) |
81 : main_task_runner_(main_task_runner), | 133 : main_task_runner_(main_task_runner), |
82 decode_task_runner_(decode_task_runner), | 134 decode_task_runner_(decode_task_runner), |
83 consumer_(consumer), | 135 consumer_(consumer), |
84 paint_scheduled_(false), | 136 paint_scheduled_(false), |
85 latest_sequence_number_(0) { | 137 weak_factory_(this) { |
86 } | 138 } |
87 | 139 |
88 RectangleUpdateDecoder::~RectangleUpdateDecoder() { | 140 SoftwareVideoRenderer::Core::~Core() { |
89 } | 141 } |
90 | 142 |
91 void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { | 143 void SoftwareVideoRenderer::Core::Initialize(const SessionConfig& config) { |
92 if (!decode_task_runner_->BelongsToCurrentThread()) { | 144 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
93 decode_task_runner_->PostTask( | |
94 FROM_HERE, base::Bind(&RectangleUpdateDecoder::Initialize, this, | |
95 config)); | |
96 return; | |
97 } | |
98 | 145 |
99 // Initialize decoder based on the selected codec. | 146 // Initialize decoder based on the selected codec. |
100 ChannelConfig::Codec codec = config.video_config().codec; | 147 ChannelConfig::Codec codec = config.video_config().codec; |
101 if (codec == ChannelConfig::CODEC_VERBATIM) { | 148 if (codec == ChannelConfig::CODEC_VERBATIM) { |
102 decoder_.reset(new VideoDecoderVerbatim()); | 149 decoder_.reset(new VideoDecoderVerbatim()); |
103 } else if (codec == ChannelConfig::CODEC_VP8) { | 150 } else if (codec == ChannelConfig::CODEC_VP8) { |
104 decoder_ = VideoDecoderVpx::CreateForVP8(); | 151 decoder_ = VideoDecoderVpx::CreateForVP8(); |
105 } else if (codec == ChannelConfig::CODEC_VP9) { | 152 } else if (codec == ChannelConfig::CODEC_VP9) { |
106 decoder_ = VideoDecoderVpx::CreateForVP9(); | 153 decoder_ = VideoDecoderVpx::CreateForVP9(); |
107 } else { | 154 } else { |
108 NOTREACHED() << "Invalid Encoding found: " << codec; | 155 NOTREACHED() << "Invalid Encoding found: " << codec; |
109 } | 156 } |
110 | 157 |
111 if (consumer_->GetPixelFormat() == FrameConsumer::FORMAT_RGBA) { | 158 if (consumer_->GetPixelFormat() == FrameConsumer::FORMAT_RGBA) { |
112 scoped_ptr<VideoDecoder> wrapper( | 159 scoped_ptr<VideoDecoder> wrapper( |
113 new RgbToBgrVideoDecoderFilter(decoder_.Pass())); | 160 new RgbToBgrVideoDecoderFilter(decoder_.Pass())); |
114 decoder_ = wrapper.Pass(); | 161 decoder_ = wrapper.Pass(); |
115 } | 162 } |
116 } | 163 } |
117 | 164 |
118 void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, | 165 void SoftwareVideoRenderer::Core::DecodePacket(scoped_ptr<VideoPacket> packet, |
119 const base::Closure& done) { | 166 const base::Closure& done) { |
120 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 167 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
121 | 168 |
122 base::ScopedClosureRunner done_runner(done); | |
123 | |
124 bool decoder_needs_reset = false; | 169 bool decoder_needs_reset = false; |
125 bool notify_size_or_dpi_change = false; | 170 bool notify_size_or_dpi_change = false; |
126 | 171 |
127 // If the packet includes screen size or DPI information, store them. | 172 // If the packet includes screen size or DPI information, store them. |
128 if (packet->format().has_screen_width() && | 173 if (packet->format().has_screen_width() && |
129 packet->format().has_screen_height()) { | 174 packet->format().has_screen_height()) { |
130 webrtc::DesktopSize source_size(packet->format().screen_width(), | 175 webrtc::DesktopSize source_size(packet->format().screen_width(), |
131 packet->format().screen_height()); | 176 packet->format().screen_height()); |
132 if (!source_size_.equals(source_size)) { | 177 if (!source_size_.equals(source_size)) { |
133 source_size_ = source_size; | 178 source_size_ = source_size; |
134 decoder_needs_reset = true; | 179 decoder_needs_reset = true; |
135 notify_size_or_dpi_change = true; | 180 notify_size_or_dpi_change = true; |
136 } | 181 } |
137 } | 182 } |
138 if (packet->format().has_x_dpi() && packet->format().has_y_dpi()) { | 183 if (packet->format().has_x_dpi() && packet->format().has_y_dpi()) { |
139 webrtc::DesktopVector source_dpi(packet->format().x_dpi(), | 184 webrtc::DesktopVector source_dpi(packet->format().x_dpi(), |
140 packet->format().y_dpi()); | 185 packet->format().y_dpi()); |
141 if (!source_dpi.equals(source_dpi_)) { | 186 if (!source_dpi.equals(source_dpi_)) { |
142 source_dpi_ = source_dpi; | 187 source_dpi_ = source_dpi; |
143 notify_size_or_dpi_change = true; | 188 notify_size_or_dpi_change = true; |
144 } | 189 } |
145 } | 190 } |
146 | 191 |
147 // If we've never seen a screen size, ignore the packet. | 192 // If we've never seen a screen size, ignore the packet. |
148 if (source_size_.is_empty()) | 193 if (source_size_.is_empty()) { |
| 194 main_task_runner_->PostTask(FROM_HERE, base::Bind(done)); |
149 return; | 195 return; |
| 196 } |
150 | 197 |
151 if (decoder_needs_reset) | 198 if (decoder_needs_reset) |
152 decoder_->Initialize(source_size_); | 199 decoder_->Initialize(source_size_); |
153 if (notify_size_or_dpi_change) | 200 if (notify_size_or_dpi_change) |
154 consumer_->SetSourceSize(source_size_, source_dpi_); | 201 consumer_->SetSourceSize(source_size_, source_dpi_); |
155 | 202 |
156 if (decoder_->DecodePacket(*packet.get())) { | 203 if (decoder_->DecodePacket(*packet.get())) { |
157 SchedulePaint(); | 204 SchedulePaint(); |
158 } else { | 205 } else { |
159 LOG(ERROR) << "DecodePacket() failed."; | 206 LOG(ERROR) << "DecodePacket() failed."; |
160 } | 207 } |
| 208 |
| 209 main_task_runner_->PostTask(FROM_HERE, base::Bind(done)); |
161 } | 210 } |
162 | 211 |
163 void RectangleUpdateDecoder::SchedulePaint() { | 212 void SoftwareVideoRenderer::Core::SchedulePaint() { |
| 213 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
164 if (paint_scheduled_) | 214 if (paint_scheduled_) |
165 return; | 215 return; |
166 paint_scheduled_ = true; | 216 paint_scheduled_ = true; |
167 decode_task_runner_->PostTask( | 217 decode_task_runner_->PostTask( |
168 FROM_HERE, base::Bind(&RectangleUpdateDecoder::DoPaint, this)); | 218 FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::DoPaint, |
| 219 weak_factory_.GetWeakPtr())); |
169 } | 220 } |
170 | 221 |
171 void RectangleUpdateDecoder::DoPaint() { | 222 void SoftwareVideoRenderer::Core::DoPaint() { |
| 223 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
172 DCHECK(paint_scheduled_); | 224 DCHECK(paint_scheduled_); |
173 paint_scheduled_ = false; | 225 paint_scheduled_ = false; |
174 | 226 |
175 // If the view size is empty or we have no output buffers ready, return. | 227 // If the view size is empty or we have no output buffers ready, return. |
176 if (buffers_.empty() || view_size_.is_empty()) | 228 if (buffers_.empty() || view_size_.is_empty()) |
177 return; | 229 return; |
178 | 230 |
179 // If no Decoder is initialized, or the host dimensions are empty, return. | 231 // If no Decoder is initialized, or the host dimensions are empty, return. |
180 if (!decoder_.get() || source_size_.is_empty()) | 232 if (!decoder_.get() || source_size_.is_empty()) |
181 return; | 233 return; |
182 | 234 |
183 // Draw the invalidated region to the buffer. | 235 // Draw the invalidated region to the buffer. |
184 webrtc::DesktopFrame* buffer = buffers_.front(); | 236 webrtc::DesktopFrame* buffer = buffers_.front(); |
185 webrtc::DesktopRegion output_region; | 237 webrtc::DesktopRegion output_region; |
186 decoder_->RenderFrame(view_size_, clip_area_, | 238 decoder_->RenderFrame(view_size_, clip_area_, |
187 buffer->data(), | 239 buffer->data(), buffer->stride(), &output_region); |
188 buffer->stride(), | |
189 &output_region); | |
190 | 240 |
191 // Notify the consumer that painting is done. | 241 // Notify the consumer that painting is done. |
192 if (!output_region.is_empty()) { | 242 if (!output_region.is_empty()) { |
193 buffers_.pop_front(); | 243 buffers_.pop_front(); |
194 consumer_->ApplyBuffer(view_size_, clip_area_, buffer, output_region); | 244 consumer_->ApplyBuffer(view_size_, clip_area_, buffer, output_region, |
| 245 *decoder_->GetImageShape()); |
195 } | 246 } |
196 } | 247 } |
197 | 248 |
198 void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { | 249 void SoftwareVideoRenderer::Core::RequestReturnBuffers( |
199 if (!decode_task_runner_->BelongsToCurrentThread()) { | 250 const base::Closure& done) { |
200 decode_task_runner_->PostTask( | 251 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
201 FROM_HERE, base::Bind(&RectangleUpdateDecoder::RequestReturnBuffers, | |
202 this, done)); | |
203 return; | |
204 } | |
205 | 252 |
206 while (!buffers_.empty()) { | 253 while (!buffers_.empty()) { |
207 consumer_->ReturnBuffer(buffers_.front()); | 254 consumer_->ReturnBuffer(buffers_.front()); |
208 buffers_.pop_front(); | 255 buffers_.pop_front(); |
209 } | 256 } |
210 | 257 |
211 if (!done.is_null()) | 258 if (!done.is_null()) |
212 done.Run(); | 259 done.Run(); |
213 } | 260 } |
214 | 261 |
215 void RectangleUpdateDecoder::DrawBuffer(webrtc::DesktopFrame* buffer) { | 262 void SoftwareVideoRenderer::Core::DrawBuffer(webrtc::DesktopFrame* buffer) { |
216 if (!decode_task_runner_->BelongsToCurrentThread()) { | 263 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
217 decode_task_runner_->PostTask( | |
218 FROM_HERE, base::Bind(&RectangleUpdateDecoder::DrawBuffer, | |
219 this, buffer)); | |
220 return; | |
221 } | |
222 | |
223 DCHECK(clip_area_.width() <= buffer->size().width() && | 264 DCHECK(clip_area_.width() <= buffer->size().width() && |
224 clip_area_.height() <= buffer->size().height()); | 265 clip_area_.height() <= buffer->size().height()); |
225 | 266 |
226 buffers_.push_back(buffer); | 267 buffers_.push_back(buffer); |
227 SchedulePaint(); | 268 SchedulePaint(); |
228 } | 269 } |
229 | 270 |
230 void RectangleUpdateDecoder::InvalidateRegion( | 271 void SoftwareVideoRenderer::Core::InvalidateRegion( |
231 const webrtc::DesktopRegion& region) { | 272 const webrtc::DesktopRegion& region) { |
232 if (!decode_task_runner_->BelongsToCurrentThread()) { | 273 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
233 decode_task_runner_->PostTask( | |
234 FROM_HERE, base::Bind(&RectangleUpdateDecoder::InvalidateRegion, | |
235 this, region)); | |
236 return; | |
237 } | |
238 | 274 |
239 if (decoder_.get()) { | 275 if (decoder_.get()) { |
240 decoder_->Invalidate(view_size_, region); | 276 decoder_->Invalidate(view_size_, region); |
241 SchedulePaint(); | 277 SchedulePaint(); |
242 } | 278 } |
243 } | 279 } |
244 | 280 |
245 void RectangleUpdateDecoder::SetOutputSizeAndClip( | 281 void SoftwareVideoRenderer::Core::SetOutputSizeAndClip( |
246 const webrtc::DesktopSize& view_size, | 282 const webrtc::DesktopSize& view_size, |
247 const webrtc::DesktopRect& clip_area) { | 283 const webrtc::DesktopRect& clip_area) { |
248 if (!decode_task_runner_->BelongsToCurrentThread()) { | 284 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
249 decode_task_runner_->PostTask( | |
250 FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSizeAndClip, | |
251 this, view_size, clip_area)); | |
252 return; | |
253 } | |
254 | 285 |
255 // The whole frame needs to be repainted if the scaling factor has changed. | 286 // The whole frame needs to be repainted if the scaling factor has changed. |
256 if (!view_size_.equals(view_size) && decoder_.get()) { | 287 if (!view_size_.equals(view_size) && decoder_.get()) { |
257 webrtc::DesktopRegion region; | 288 webrtc::DesktopRegion region; |
258 region.AddRect(webrtc::DesktopRect::MakeSize(view_size)); | 289 region.AddRect(webrtc::DesktopRect::MakeSize(view_size)); |
259 decoder_->Invalidate(view_size, region); | 290 decoder_->Invalidate(view_size, region); |
260 } | 291 } |
261 | 292 |
262 if (!view_size_.equals(view_size) || | 293 if (!view_size_.equals(view_size) || |
263 !clip_area_.equals(clip_area)) { | 294 !clip_area_.equals(clip_area)) { |
(...skipping 10 matching lines...) Expand all Loading... |
274 i = buffers_.erase(i); | 305 i = buffers_.erase(i); |
275 } else { | 306 } else { |
276 ++i; | 307 ++i; |
277 } | 308 } |
278 } | 309 } |
279 | 310 |
280 SchedulePaint(); | 311 SchedulePaint(); |
281 } | 312 } |
282 } | 313 } |
283 | 314 |
284 const webrtc::DesktopRegion* RectangleUpdateDecoder::GetBufferShape() { | 315 SoftwareVideoRenderer::SoftwareVideoRenderer( |
285 return decoder_->GetImageShape(); | 316 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 317 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
| 318 scoped_refptr<FrameConsumerProxy> consumer) |
| 319 : decode_task_runner_(decode_task_runner), |
| 320 core_(new Core(main_task_runner, decode_task_runner, consumer)), |
| 321 latest_sequence_number_(0), |
| 322 weak_factory_(this) { |
| 323 DCHECK(CalledOnValidThread()); |
286 } | 324 } |
287 | 325 |
288 void RectangleUpdateDecoder::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, | 326 SoftwareVideoRenderer::~SoftwareVideoRenderer() { |
| 327 DCHECK(CalledOnValidThread()); |
| 328 decode_task_runner_->DeleteSoon(FROM_HERE, core_.release()); |
| 329 } |
| 330 |
| 331 void SoftwareVideoRenderer::Initialize( |
| 332 const protocol::SessionConfig& config) { |
| 333 DCHECK(CalledOnValidThread()); |
| 334 decode_task_runner_->PostTask( |
| 335 FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::Initialize, |
| 336 base::Unretained(core_.get()), config)); |
| 337 } |
| 338 |
| 339 ChromotingStats* SoftwareVideoRenderer::GetStats() { |
| 340 DCHECK(CalledOnValidThread()); |
| 341 return &stats_; |
| 342 } |
| 343 |
| 344 void SoftwareVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
289 const base::Closure& done) { | 345 const base::Closure& done) { |
290 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 346 DCHECK(CalledOnValidThread()); |
291 | 347 |
292 // If the video packet is empty then drop it. Empty packets are used to | 348 // If the video packet is empty then drop it. Empty packets are used to |
293 // maintain activity on the network. | 349 // maintain activity on the network. |
294 if (!packet->has_data() || packet->data().size() == 0) { | 350 if (!packet->has_data() || packet->data().size() == 0) { |
295 done.Run(); | 351 done.Run(); |
296 return; | 352 return; |
297 } | 353 } |
298 | 354 |
299 // Add one frame to the counter. | 355 // Add one frame to the counter. |
300 stats_.video_frame_rate()->Record(1); | 356 stats_.video_frame_rate()->Record(1); |
301 | 357 |
302 // Record other statistics received from host. | 358 // Record other statistics received from host. |
303 stats_.video_bandwidth()->Record(packet->data().size()); | 359 stats_.video_bandwidth()->Record(packet->data().size()); |
304 if (packet->has_capture_time_ms()) | 360 if (packet->has_capture_time_ms()) |
305 stats_.video_capture_ms()->Record(packet->capture_time_ms()); | 361 stats_.video_capture_ms()->Record(packet->capture_time_ms()); |
306 if (packet->has_encode_time_ms()) | 362 if (packet->has_encode_time_ms()) |
307 stats_.video_encode_ms()->Record(packet->encode_time_ms()); | 363 stats_.video_encode_ms()->Record(packet->encode_time_ms()); |
308 if (packet->has_client_sequence_number() && | 364 if (packet->has_client_sequence_number() && |
309 packet->client_sequence_number() > latest_sequence_number_) { | 365 packet->client_sequence_number() > latest_sequence_number_) { |
310 latest_sequence_number_ = packet->client_sequence_number(); | 366 latest_sequence_number_ = packet->client_sequence_number(); |
311 base::TimeDelta round_trip_latency = | 367 base::TimeDelta round_trip_latency = |
312 base::Time::Now() - | 368 base::Time::Now() - |
313 base::Time::FromInternalValue(packet->client_sequence_number()); | 369 base::Time::FromInternalValue(packet->client_sequence_number()); |
314 stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); | 370 stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); |
315 } | 371 } |
316 | 372 |
317 // Measure the latency between the last packet being received and presented. | 373 // Measure the latency between the last packet being received and presented. |
318 base::Time decode_start = base::Time::Now(); | 374 base::Time decode_start = base::Time::Now(); |
319 | 375 |
320 base::Closure decode_done = base::Bind( | 376 base::Closure decode_done = base::Bind(&SoftwareVideoRenderer::OnPacketDone, |
321 &RectangleUpdateDecoder::OnPacketDone, this, decode_start, done); | 377 weak_factory_.GetWeakPtr(), |
| 378 decode_start, done); |
322 | 379 |
323 decode_task_runner_->PostTask(FROM_HERE, base::Bind( | 380 decode_task_runner_->PostTask(FROM_HERE, base::Bind( |
324 &RectangleUpdateDecoder::DecodePacket, this, | 381 &SoftwareVideoRenderer::Core::DecodePacket, |
325 base::Passed(&packet), decode_done)); | 382 base::Unretained(core_.get()), base::Passed(&packet), decode_done)); |
326 } | 383 } |
327 | 384 |
328 void RectangleUpdateDecoder::OnPacketDone(base::Time decode_start, | 385 void SoftwareVideoRenderer::DrawBuffer(webrtc::DesktopFrame* buffer) { |
| 386 decode_task_runner_->PostTask( |
| 387 FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::DrawBuffer, |
| 388 base::Unretained(core_.get()), buffer)); |
| 389 } |
| 390 |
| 391 void SoftwareVideoRenderer::InvalidateRegion( |
| 392 const webrtc::DesktopRegion& region) { |
| 393 decode_task_runner_->PostTask( |
| 394 FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::InvalidateRegion, |
| 395 base::Unretained(core_.get()), region)); |
| 396 } |
| 397 |
| 398 void SoftwareVideoRenderer::RequestReturnBuffers(const base::Closure& done) { |
| 399 decode_task_runner_->PostTask( |
| 400 FROM_HERE, |
| 401 base::Bind(&SoftwareVideoRenderer::Core::RequestReturnBuffers, |
| 402 base::Unretained(core_.get()), done)); |
| 403 } |
| 404 |
| 405 void SoftwareVideoRenderer::SetOutputSizeAndClip( |
| 406 const webrtc::DesktopSize& view_size, |
| 407 const webrtc::DesktopRect& clip_area) { |
| 408 decode_task_runner_->PostTask( |
| 409 FROM_HERE, |
| 410 base::Bind(&SoftwareVideoRenderer::Core::SetOutputSizeAndClip, |
| 411 base::Unretained(core_.get()), view_size, clip_area)); |
| 412 } |
| 413 |
| 414 void SoftwareVideoRenderer::OnPacketDone(base::Time decode_start, |
329 const base::Closure& done) { | 415 const base::Closure& done) { |
330 if (!main_task_runner_->BelongsToCurrentThread()) { | 416 DCHECK(CalledOnValidThread()); |
331 main_task_runner_->PostTask(FROM_HERE, base::Bind( | |
332 &RectangleUpdateDecoder::OnPacketDone, this, | |
333 decode_start, done)); | |
334 return; | |
335 } | |
336 | 417 |
337 // Record the latency between the packet being received and presented. | 418 // Record the latency between the packet being received and presented. |
338 stats_.video_decode_ms()->Record( | 419 stats_.video_decode_ms()->Record( |
339 (base::Time::Now() - decode_start).InMilliseconds()); | 420 (base::Time::Now() - decode_start).InMilliseconds()); |
340 | 421 |
341 done.Run(); | 422 done.Run(); |
342 } | 423 } |
343 | 424 |
344 ChromotingStats* RectangleUpdateDecoder::GetStats() { | |
345 DCHECK(main_task_runner_->BelongsToCurrentThread()); | |
346 return &stats_; | |
347 } | |
348 | |
349 } // namespace remoting | 425 } // namespace remoting |
OLD | NEW |