| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/rectangle_update_decoder.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "remoting/base/decoder.h" | 9 #include "remoting/base/decoder.h" |
| 10 #include "remoting/base/decoder_row_based.h" | 10 #include "remoting/base/decoder_row_based.h" |
| 11 #include "remoting/base/decoder_vp8.h" | 11 #include "remoting/base/decoder_vp8.h" |
| 12 #include "remoting/base/util.h" | 12 #include "remoting/base/util.h" |
| 13 #include "remoting/client/frame_consumer.h" | 13 #include "remoting/client/frame_consumer.h" |
| 14 #include "remoting/protocol/session_config.h" | 14 #include "remoting/protocol/session_config.h" |
| 15 | 15 |
| 16 using remoting::protocol::ChannelConfig; | 16 using remoting::protocol::ChannelConfig; |
| 17 using remoting::protocol::SessionConfig; | 17 using remoting::protocol::SessionConfig; |
| 18 | 18 |
| 19 namespace remoting { | 19 namespace remoting { |
| 20 | 20 |
| 21 class PartialFrameCleanup : public Task { | 21 class PartialFrameCleanup : public Task { |
| 22 public: | 22 public: |
| 23 PartialFrameCleanup(media::VideoFrame* frame, UpdatedRects* rects, | 23 PartialFrameCleanup(media::VideoFrame* frame, RectVector* rects, |
| 24 RectangleUpdateDecoder* decoder) | 24 RectangleUpdateDecoder* decoder) |
| 25 : frame_(frame), rects_(rects), decoder_(decoder) { | 25 : frame_(frame), rects_(rects), decoder_(decoder) { |
| 26 } | 26 } |
| 27 | 27 |
| 28 virtual void Run() { | 28 virtual void Run() { |
| 29 delete rects_; | 29 delete rects_; |
| 30 frame_ = NULL; | 30 frame_ = NULL; |
| 31 | 31 |
| 32 // There maybe pending request to refresh rectangles. | 32 // There maybe pending request to refresh rectangles. |
| 33 decoder_->OnFrameConsumed(); | 33 decoder_->OnFrameConsumed(); |
| 34 decoder_ = NULL; | 34 decoder_ = NULL; |
| 35 } | 35 } |
| 36 | 36 |
| 37 private: | 37 private: |
| 38 scoped_refptr<media::VideoFrame> frame_; | 38 scoped_refptr<media::VideoFrame> frame_; |
| 39 UpdatedRects* rects_; | 39 RectVector* rects_; |
| 40 scoped_refptr<RectangleUpdateDecoder> decoder_; | 40 scoped_refptr<RectangleUpdateDecoder> decoder_; |
| 41 }; | 41 }; |
| 42 | 42 |
| 43 RectangleUpdateDecoder::RectangleUpdateDecoder(MessageLoop* message_loop, | 43 RectangleUpdateDecoder::RectangleUpdateDecoder(MessageLoop* message_loop, |
| 44 FrameConsumer* consumer) | 44 FrameConsumer* consumer) |
| 45 : message_loop_(message_loop), | 45 : message_loop_(message_loop), |
| 46 consumer_(consumer), | 46 consumer_(consumer), |
| 47 frame_is_new_(false), | 47 frame_is_new_(false), |
| 48 frame_is_consuming_(false) { | 48 frame_is_consuming_(false) { |
| 49 } | 49 } |
| 50 | 50 |
| 51 RectangleUpdateDecoder::~RectangleUpdateDecoder() { | 51 RectangleUpdateDecoder::~RectangleUpdateDecoder() { |
| 52 } | 52 } |
| 53 | 53 |
| 54 void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { | 54 void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
| 55 initial_screen_size_ = gfx::Size(config.initial_resolution().width, | 55 initial_screen_size_ = SkISize::Make(config.initial_resolution().width, |
| 56 config.initial_resolution().height); | 56 config.initial_resolution().height); |
| 57 | 57 |
| 58 // Initialize decoder based on the selected codec. | 58 // Initialize decoder based on the selected codec. |
| 59 ChannelConfig::Codec codec = config.video_config().codec; | 59 ChannelConfig::Codec codec = config.video_config().codec; |
| 60 if (codec == ChannelConfig::CODEC_VERBATIM) { | 60 if (codec == ChannelConfig::CODEC_VERBATIM) { |
| 61 decoder_.reset(DecoderRowBased::CreateVerbatimDecoder()); | 61 decoder_.reset(DecoderRowBased::CreateVerbatimDecoder()); |
| 62 } else if (codec == ChannelConfig::CODEC_ZIP) { | 62 } else if (codec == ChannelConfig::CODEC_ZIP) { |
| 63 decoder_.reset(DecoderRowBased::CreateZlibDecoder()); | 63 decoder_.reset(DecoderRowBased::CreateZlibDecoder()); |
| 64 } else if (codec == ChannelConfig::CODEC_VP8) { | 64 } else if (codec == ChannelConfig::CODEC_VP8) { |
| 65 decoder_.reset(new DecoderVp8()); | 65 decoder_.reset(new DecoderVp8()); |
| 66 } else { | 66 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 91 NewRunnableMethod( | 91 NewRunnableMethod( |
| 92 this, | 92 this, |
| 93 &RectangleUpdateDecoder::AllocateFrame, packet, done)); | 93 &RectangleUpdateDecoder::AllocateFrame, packet, done)); |
| 94 return; | 94 return; |
| 95 } | 95 } |
| 96 base::ScopedTaskRunner done_runner(done); | 96 base::ScopedTaskRunner done_runner(done); |
| 97 | 97 |
| 98 // Find the required frame size. | 98 // Find the required frame size. |
| 99 bool has_screen_size = packet->format().has_screen_width() && | 99 bool has_screen_size = packet->format().has_screen_width() && |
| 100 packet->format().has_screen_height(); | 100 packet->format().has_screen_height(); |
| 101 gfx::Size screen_size(packet->format().screen_width(), | 101 SkISize screen_size(SkISize::Make(packet->format().screen_width(), |
| 102 packet->format().screen_height()); | 102 packet->format().screen_height())); |
| 103 if (!has_screen_size) | 103 if (!has_screen_size) |
| 104 screen_size = initial_screen_size_; | 104 screen_size = initial_screen_size_; |
| 105 | 105 |
| 106 // Find the current frame size. | 106 // Find the current frame size. |
| 107 gfx::Size frame_size(0, 0); | 107 int width = 0; |
| 108 if (frame_) | 108 int height = 0; |
| 109 frame_size = gfx::Size(static_cast<int>(frame_->width()), | 109 if (frame_) { |
| 110 static_cast<int>(frame_->height())); | 110 width = static_cast<int>(frame_->width()); |
| 111 height = static_cast<int>(frame_->height()); |
| 112 } |
| 113 |
| 114 SkISize frame_size(SkISize::Make(width, height)); |
| 111 | 115 |
| 112 // Allocate a new frame, if necessary. | 116 // Allocate a new frame, if necessary. |
| 113 if ((!frame_) || (has_screen_size && (screen_size != frame_size))) { | 117 if ((!frame_) || (has_screen_size && (screen_size != frame_size))) { |
| 114 if (frame_) { | 118 if (frame_) { |
| 115 consumer_->ReleaseFrame(frame_); | 119 consumer_->ReleaseFrame(frame_); |
| 116 frame_ = NULL; | 120 frame_ = NULL; |
| 117 } | 121 } |
| 118 | 122 |
| 119 consumer_->AllocateFrame(media::VideoFrame::RGB32, | 123 consumer_->AllocateFrame(media::VideoFrame::RGB32, |
| 120 screen_size.width(), screen_size.height(), | 124 screen_size.width(), screen_size.height(), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 vertical_ratio)); | 172 vertical_ratio)); |
| 169 return; | 173 return; |
| 170 } | 174 } |
| 171 | 175 |
| 172 // TODO(hclam): If the scale ratio has changed we should reallocate a | 176 // TODO(hclam): If the scale ratio has changed we should reallocate a |
| 173 // VideoFrame of different size. However if the scale ratio is always | 177 // VideoFrame of different size. However if the scale ratio is always |
| 174 // smaller than 1.0 we can use the same video frame. | 178 // smaller than 1.0 we can use the same video frame. |
| 175 decoder_->SetScaleRatios(horizontal_ratio, vertical_ratio); | 179 decoder_->SetScaleRatios(horizontal_ratio, vertical_ratio); |
| 176 } | 180 } |
| 177 | 181 |
| 178 void RectangleUpdateDecoder::UpdateClipRect(const gfx::Rect& new_clip_rect) { | 182 void RectangleUpdateDecoder::UpdateClipRect(const SkIRect& new_clip_rect) { |
| 179 if (message_loop_ != MessageLoop::current()) { | 183 if (message_loop_ != MessageLoop::current()) { |
| 180 message_loop_->PostTask( | 184 message_loop_->PostTask( |
| 181 FROM_HERE, | 185 FROM_HERE, |
| 182 NewRunnableMethod( | 186 NewRunnableMethod( |
| 183 this, | 187 this, |
| 184 &RectangleUpdateDecoder::UpdateClipRect, new_clip_rect)); | 188 &RectangleUpdateDecoder::UpdateClipRect, new_clip_rect)); |
| 185 return; | 189 return; |
| 186 } | 190 } |
| 187 | 191 |
| 188 if (new_clip_rect == clip_rect_ || !decoder_.get()) | 192 if (new_clip_rect == clip_rect_ || !decoder_.get()) |
| 189 return; | 193 return; |
| 190 | 194 |
| 191 // Find out the rectangles to show because of clip rect is updated. | 195 // Find out the rectangles to show because of clip rect is updated. |
| 192 if (new_clip_rect.y() < clip_rect_.y()) { | 196 if (new_clip_rect.fTop < clip_rect_.fTop) { |
| 193 refresh_rects_.push_back( | 197 refresh_rects_.push_back( |
| 194 gfx::Rect(new_clip_rect.x(), | 198 SkIRect::MakeXYWH(new_clip_rect.fLeft, |
| 195 new_clip_rect.y(), | 199 new_clip_rect.fTop, |
| 196 new_clip_rect.width(), | 200 new_clip_rect.width(), |
| 197 clip_rect_.y() - new_clip_rect.y())); | 201 clip_rect_.fTop - new_clip_rect.fTop)); |
| 198 } | 202 } |
| 199 | 203 |
| 200 if (new_clip_rect.x() < clip_rect_.x()) { | 204 if (new_clip_rect.fLeft < clip_rect_.fLeft) { |
| 201 refresh_rects_.push_back( | 205 refresh_rects_.push_back( |
| 202 gfx::Rect(new_clip_rect.x(), | 206 SkIRect::MakeXYWH(new_clip_rect.fLeft, |
| 203 clip_rect_.y(), | 207 clip_rect_.fTop, |
| 204 clip_rect_.x() - new_clip_rect.x(), | 208 clip_rect_.fLeft - new_clip_rect.fLeft, |
| 205 clip_rect_.height())); | 209 clip_rect_.height())); |
| 206 } | 210 } |
| 207 | 211 |
| 208 if (new_clip_rect.right() > clip_rect_.right()) { | 212 if (new_clip_rect.fRight > clip_rect_.fRight) { |
| 209 refresh_rects_.push_back( | 213 refresh_rects_.push_back( |
| 210 gfx::Rect(clip_rect_.right(), | 214 SkIRect::MakeXYWH(clip_rect_.fRight, |
| 211 clip_rect_.y(), | 215 clip_rect_.fTop, |
| 212 new_clip_rect.right() - clip_rect_.right(), | 216 new_clip_rect.fRight - clip_rect_.fRight, |
| 213 new_clip_rect.height())); | 217 new_clip_rect.height())); |
| 214 } | 218 } |
| 215 | 219 |
| 216 if (new_clip_rect.bottom() > clip_rect_.bottom()) { | 220 if (new_clip_rect.fBottom > clip_rect_.fBottom) { |
| 217 refresh_rects_.push_back( | 221 refresh_rects_.push_back( |
| 218 gfx::Rect(new_clip_rect.x(), | 222 SkIRect::MakeXYWH(new_clip_rect.fLeft, |
| 219 clip_rect_.bottom(), | 223 clip_rect_.fBottom, |
| 220 new_clip_rect.width(), | 224 new_clip_rect.width(), |
| 221 new_clip_rect.bottom() - clip_rect_.bottom())); | 225 new_clip_rect.fBottom - clip_rect_.fBottom)); |
| 222 } | 226 } |
| 223 | 227 |
| 224 clip_rect_ = new_clip_rect; | 228 clip_rect_ = new_clip_rect; |
| 225 decoder_->SetClipRect(new_clip_rect); | 229 decoder_->SetClipRect(new_clip_rect); |
| 226 DoRefresh(); | 230 DoRefresh(); |
| 227 } | 231 } |
| 228 | 232 |
| 229 void RectangleUpdateDecoder::RefreshFullFrame() { | 233 void RectangleUpdateDecoder::RefreshFullFrame() { |
| 230 if (message_loop_ != MessageLoop::current()) { | 234 if (message_loop_ != MessageLoop::current()) { |
| 231 message_loop_->PostTask( | 235 message_loop_->PostTask( |
| 232 FROM_HERE, | 236 FROM_HERE, |
| 233 NewRunnableMethod(this, &RectangleUpdateDecoder::RefreshFullFrame)); | 237 NewRunnableMethod(this, &RectangleUpdateDecoder::RefreshFullFrame)); |
| 234 return; | 238 return; |
| 235 } | 239 } |
| 236 | 240 |
| 237 // If a video frame or the decoder is not allocated yet then don't | 241 // If a video frame or the decoder is not allocated yet then don't |
| 238 // save the refresh rectangle to avoid wasted computation. | 242 // save the refresh rectangle to avoid wasted computation. |
| 239 if (!frame_ || !decoder_.get()) | 243 if (!frame_ || !decoder_.get()) |
| 240 return; | 244 return; |
| 241 | 245 |
| 242 refresh_rects_.push_back( | 246 refresh_rects_.push_back( |
| 243 gfx::Rect(0, 0, static_cast<int>(frame_->width()), | 247 SkIRect::MakeWH(static_cast<int>(frame_->width()), |
| 244 static_cast<int>(frame_->height()))); | 248 static_cast<int>(frame_->height()))); |
| 245 DoRefresh(); | 249 DoRefresh(); |
| 246 } | 250 } |
| 247 | 251 |
| 248 void RectangleUpdateDecoder::SubmitToConsumer() { | 252 void RectangleUpdateDecoder::SubmitToConsumer() { |
| 249 // A frame is not allocated yet, we can reach here because of a refresh | 253 // A frame is not allocated yet, we can reach here because of a refresh |
| 250 // request. | 254 // request. |
| 251 if (!frame_) | 255 if (!frame_) |
| 252 return; | 256 return; |
| 253 | 257 |
| 254 UpdatedRects* dirty_rects = new UpdatedRects(); | 258 RectVector* dirty_rects = new RectVector(); |
| 255 decoder_->GetUpdatedRects(dirty_rects); | 259 decoder_->GetUpdatedRects(dirty_rects); |
| 256 | 260 |
| 257 frame_is_consuming_ = true; | 261 frame_is_consuming_ = true; |
| 258 consumer_->OnPartialFrameOutput( | 262 consumer_->OnPartialFrameOutput( |
| 259 frame_, dirty_rects, | 263 frame_, dirty_rects, |
| 260 new PartialFrameCleanup(frame_, dirty_rects, this)); | 264 new PartialFrameCleanup(frame_, dirty_rects, this)); |
| 261 } | 265 } |
| 262 | 266 |
| 263 void RectangleUpdateDecoder::DoRefresh() { | 267 void RectangleUpdateDecoder::DoRefresh() { |
| 264 DCHECK_EQ(message_loop_, MessageLoop::current()); | 268 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 277 FROM_HERE, | 281 FROM_HERE, |
| 278 NewRunnableMethod(this, &RectangleUpdateDecoder::OnFrameConsumed)); | 282 NewRunnableMethod(this, &RectangleUpdateDecoder::OnFrameConsumed)); |
| 279 return; | 283 return; |
| 280 } | 284 } |
| 281 | 285 |
| 282 frame_is_consuming_ = false; | 286 frame_is_consuming_ = false; |
| 283 DoRefresh(); | 287 DoRefresh(); |
| 284 } | 288 } |
| 285 | 289 |
| 286 } // namespace remoting | 290 } // namespace remoting |
| OLD | NEW |