Chromium Code Reviews| Index: remoting/client/rectangle_update_decoder.cc |
| diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc |
| index 673c2a037061f78d23afbd4c916b6c5995e750a7..14f768ff85462317136f992cd8a0014e36763508 100644 |
| --- a/remoting/client/rectangle_update_decoder.cc |
| +++ b/remoting/client/rectangle_update_decoder.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/message_loop_proxy.h" |
| +#include "ppapi/cpp/image_data.h" |
| #include "remoting/base/decoder.h" |
| #include "remoting/base/decoder_row_based.h" |
| #include "remoting/base/decoder_vp8.h" |
| @@ -27,8 +28,9 @@ RectangleUpdateDecoder::RectangleUpdateDecoder( |
| : message_loop_(message_loop), |
| consumer_(consumer), |
| screen_size_(SkISize::Make(0, 0)), |
| - clip_rect_(SkIRect::MakeEmpty()), |
| - decoder_needs_reset_(false) { |
| + update_pending_(false), |
| + view_size_(SkISize::Make(0, 0)), |
| + clip_area_(SkIRect::MakeEmpty()) { |
| } |
| RectangleUpdateDecoder::~RectangleUpdateDecoder() { |
| @@ -56,24 +58,19 @@ void RectangleUpdateDecoder::DecodePacket(const VideoPacket* packet, |
| this, packet, done)); |
| return; |
| } |
| - AllocateFrame(packet, done); |
| -} |
| -void RectangleUpdateDecoder::AllocateFrame(const VideoPacket* packet, |
| - const base::Closure& done) { |
| - if (!message_loop_->BelongsToCurrentThread()) { |
| - message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::AllocateFrame, |
| - this, packet, done)); |
| - return; |
| - } |
| base::ScopedClosureRunner done_runner(done); |
| + bool decoder_needs_reset = false; |
| // If the packet includes a screen size, store it. |
| if (packet->format().has_screen_width() && |
| packet->format().has_screen_height()) { |
| - screen_size_.set(packet->format().screen_width(), |
| - packet->format().screen_height()); |
| + SkISize screen_size = SkISize::Make(packet->format().screen_width(), |
| + packet->format().screen_height()); |
| + if (screen_size_ != screen_size) { |
| + screen_size_ = screen_size; |
| + decoder_needs_reset = true; |
|
Wez
2012/02/07 01:56:31
So we really need to reset the decoder on host res
alexeypa (please no reviews)
2012/02/15 23:06:22
I don't know but I'd like to avoid adding more cha
|
| + } |
| } |
| // If we've never seen a screen size, ignore the packet. |
| @@ -81,42 +78,9 @@ void RectangleUpdateDecoder::AllocateFrame(const VideoPacket* packet, |
| return; |
| } |
| - // Ensure the output frame is the right size. |
| - SkISize frame_size = SkISize::Make(0, 0); |
| - if (frame_) |
| - frame_size.set(frame_->width(), frame_->height()); |
| - |
| - // Allocate a new frame, if necessary. |
| - if ((!frame_) || (screen_size_ != frame_size)) { |
| - if (frame_) { |
| - consumer_->ReleaseFrame(frame_); |
| - frame_ = NULL; |
| - } |
| - |
| - consumer_->AllocateFrame( |
| - media::VideoFrame::RGB32, screen_size_, &frame_, |
| - base::Bind(&RectangleUpdateDecoder::ProcessPacketData, |
| - this, packet, done_runner.Release())); |
| - decoder_needs_reset_ = true; |
| - return; |
| - } |
| - ProcessPacketData(packet, done_runner.Release()); |
| -} |
| - |
| -void RectangleUpdateDecoder::ProcessPacketData( |
| - const VideoPacket* packet, const base::Closure& done) { |
| - if (!message_loop_->BelongsToCurrentThread()) { |
| - message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::ProcessPacketData, |
| - this, packet, done)); |
| - return; |
| - } |
| - base::ScopedClosureRunner done_runner(done); |
| - |
| - if (decoder_needs_reset_) { |
| + if (decoder_needs_reset) { |
| decoder_->Reset(); |
| - decoder_->Initialize(frame_); |
| - decoder_needs_reset_ = false; |
| + decoder_->Initialize(screen_size_); |
| } |
| if (!decoder_->IsReadyForData()) { |
| @@ -129,106 +93,59 @@ void RectangleUpdateDecoder::ProcessPacketData( |
| SubmitToConsumer(); |
| } |
| -void RectangleUpdateDecoder::SetOutputSize(const SkISize& size) { |
| +void RectangleUpdateDecoder::RefreshFullFrame() { |
| if (!message_loop_->BelongsToCurrentThread()) { |
| message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSize, |
| - this, size)); |
| + FROM_HERE, base::Bind(&RectangleUpdateDecoder::RefreshFullFrame, this)); |
| return; |
| } |
| - // TODO(wez): Refresh the frame only if the ratio has changed. |
| - if (frame_) { |
| - SkIRect frame_rect = SkIRect::MakeWH(frame_->width(), frame_->height()); |
| - refresh_region_.op(frame_rect, SkRegion::kUnion_Op); |
| - } |
| - |
| - // TODO(hclam): If the scale ratio has changed we should reallocate a |
| - // VideoFrame of different size. However if the scale ratio is always |
| - // smaller than 1.0 we can use the same video frame. |
| if (decoder_.get()) { |
| - decoder_->SetOutputSize(size); |
| - RefreshFullFrame(); |
| + SkRegion region; |
| + region.op(SkIRect::MakeSize(screen_size_), SkRegion::kUnion_Op); |
| + decoder_->UpdateRegion(region); |
| + SubmitToConsumer(); |
| } |
| } |
| -void RectangleUpdateDecoder::UpdateClipRect(const SkIRect& new_clip_rect) { |
| - if (!message_loop_->BelongsToCurrentThread()) { |
| - message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::UpdateClipRect, |
| - this, new_clip_rect)); |
| - return; |
| - } |
| - |
| - if (new_clip_rect == clip_rect_ || !decoder_.get()) |
| - return; |
| +void RectangleUpdateDecoder::SubmitToConsumer() { |
| + DCHECK(message_loop_->BelongsToCurrentThread()); |
| - // TODO(wez): Only refresh newly-exposed portions of the frame. |
| - if (frame_) { |
| - SkIRect frame_rect = SkIRect::MakeWH(frame_->width(), frame_->height()); |
| - refresh_region_.op(frame_rect, SkRegion::kUnion_Op); |
| + if (!update_pending_) { |
| + // Make sure OnFrameReady() will not be called again until OnPaintFrame() |
| + // is invoked. |
| + update_pending_ = true; |
| + consumer_->OnFrameReady( |
| + screen_size_, |
| + &view_size_, &clip_area_, &backing_store_, |
| + base::Bind(&RectangleUpdateDecoder::OnPaintFrame, this)); |
| } |
| - |
| - clip_rect_ = new_clip_rect; |
| - decoder_->SetClipRect(new_clip_rect); |
| - |
| - // TODO(wez): Defer refresh so that multiple events can be batched. |
| - DoRefresh(); |
| } |
| -void RectangleUpdateDecoder::RefreshFullFrame() { |
| +void RectangleUpdateDecoder::OnPaintFrame() { |
| if (!message_loop_->BelongsToCurrentThread()) { |
| message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::RefreshFullFrame, this)); |
| + FROM_HERE, base::Bind(&RectangleUpdateDecoder::OnPaintFrame, |
| + this)); |
| return; |
| } |
| - // If a video frame or the decoder is not allocated yet then don't |
| - // save the refresh rectangle to avoid wasted computation. |
| - if (!frame_ || !decoder_.get()) |
| - return; |
| - |
| - SkIRect frame_rect = SkIRect::MakeWH(frame_->width(), frame_->height()); |
| - refresh_region_.op(frame_rect, SkRegion::kUnion_Op); |
| - |
| - DoRefresh(); |
| -} |
| - |
| -void RectangleUpdateDecoder::SubmitToConsumer() { |
| - // A frame is not allocated yet, we can reach here because of a refresh |
| - // request. |
| - if (!frame_) |
| - return; |
| + update_pending_ = false; |
| - SkRegion* dirty_region = new SkRegion; |
| - decoder_->GetUpdatedRegion(dirty_region); |
| + // Skip painting if the backing store is not ready yet. |
| + if (backing_store_.get() && !backing_store_->is_null()) { |
| + // Draw the updated region to the backing store. |
| + scoped_ptr<SkRegion> output_region(new SkRegion()); |
| + decoder_->Draw(view_size_, clip_area_, |
| + reinterpret_cast<uint8*>(backing_store_->data()), |
| + backing_store_->stride(), |
| + output_region.get()); |
| - consumer_->OnPartialFrameOutput(frame_, dirty_region, base::Bind( |
| - &RectangleUpdateDecoder::OnFrameConsumed, this, dirty_region)); |
| -} |
| - |
| -void RectangleUpdateDecoder::DoRefresh() { |
| - DCHECK(message_loop_->BelongsToCurrentThread()); |
| - |
| - if (refresh_region_.isEmpty()) |
| - return; |
| - |
| - decoder_->RefreshRegion(refresh_region_); |
| - refresh_region_.setEmpty(); |
| - SubmitToConsumer(); |
| -} |
| - |
| -void RectangleUpdateDecoder::OnFrameConsumed(SkRegion* region) { |
| - if (!message_loop_->BelongsToCurrentThread()) { |
| - message_loop_->PostTask( |
| - FROM_HERE, base::Bind(&RectangleUpdateDecoder::OnFrameConsumed, |
| - this, region)); |
| - return; |
| + // Notify the consumer that painting is done. |
| + consumer_->OnPaintDone(backing_store_.Pass(), output_region.Pass()); |
| + } else { |
| + LOG(ERROR) << "Backing store is not available."; |
| } |
| - |
| - delete region; |
| - |
| - DoRefresh(); |
| } |
| } // namespace remoting |