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 |