Index: remoting/client/rectangle_update_decoder.cc |
diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc |
index 3482527e90435fee611247f191f1d07e0a5f70dd..bae064545e96efdce303168ef75761b70f631359 100644 |
--- a/remoting/client/rectangle_update_decoder.cc |
+++ b/remoting/client/rectangle_update_decoder.cc |
@@ -4,6 +4,8 @@ |
#include "remoting/client/rectangle_update_decoder.h" |
+#include <list> |
+ |
#include "base/bind.h" |
#include "base/callback.h" |
#include "base/callback_helpers.h" |
@@ -74,7 +76,74 @@ class RgbToBgrVideoDecoderFilter : public VideoDecoder { |
scoped_ptr<VideoDecoder> parent_; |
}; |
-RectangleUpdateDecoder::RectangleUpdateDecoder( |
+class RectangleUpdateDecoder::Core : public base::RefCountedThreadSafe<Core> { |
+ public: |
+ Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
+ scoped_refptr<FrameConsumerProxy> consumer); |
+ |
+ // VideoProcessor implementation. |
+ void Initialize(const protocol::SessionConfig& config); |
+ ChromotingStats* GetStats(); |
+ void ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
+ const base::Closure& done); |
+ |
+ // FrameProducer implementation. These methods may be called before we are |
+ // Initialize()d, or we know the source screen size. |
+ void DrawBuffer(webrtc::DesktopFrame* buffer); |
+ void InvalidateRegion(const webrtc::DesktopRegion& region); |
+ void RequestReturnBuffers(const base::Closure& done); |
+ void SetOutputSizeAndClip( |
+ const webrtc::DesktopSize& view_size, |
+ const webrtc::DesktopRect& clip_area); |
+ const webrtc::DesktopRegion* GetBufferShape(); |
+ |
+ private: |
+ friend class base::RefCountedThreadSafe<Core>; |
+ virtual ~Core(); |
+ |
+ // Paints the invalidated region to the next available buffer and returns it |
+ // to the consumer. |
+ void SchedulePaint(); |
+ void DoPaint(); |
+ |
+ // Decodes the contents of |packet|. DecodePacket may keep a reference to |
+ // |packet| so the |packet| must remain alive and valid until |done| is |
+ // executed. |
+ void DecodePacket(scoped_ptr<VideoPacket> packet, const base::Closure& done); |
+ |
+ // Callback method when a VideoPacket is processed. |decode_start| contains |
+ // the timestamp when the packet will start to be processed. |
+ void OnPacketDone(base::Time decode_start, const base::Closure& done); |
+ |
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_; |
+ scoped_refptr<FrameConsumerProxy> consumer_; |
+ scoped_ptr<VideoDecoder> decoder_; |
+ |
+ // Remote screen size in pixels. |
+ webrtc::DesktopSize source_size_; |
+ |
+ // Vertical and horizontal DPI of the remote screen. |
+ webrtc::DesktopVector source_dpi_; |
+ |
+ // The current dimensions of the frame consumer view. |
+ webrtc::DesktopSize view_size_; |
+ webrtc::DesktopRect clip_area_; |
+ |
+ // The drawing buffers supplied by the frame consumer. |
+ std::list<webrtc::DesktopFrame*> buffers_; |
+ |
+ // Flag used to coalesce runs of SchedulePaint()s into a single DoPaint(). |
+ bool paint_scheduled_; |
+ |
+ ChromotingStats stats_; |
Wez
2014/01/14 16:23:14
If you move ProcessVideoPacket and OnDecodeDone ba
Sergey Ulanov
2014/01/15 00:58:17
Done.
|
+ |
+ // Keep track of the most recent sequence number bounced back from the host. |
+ int64 latest_sequence_number_; |
+}; |
+ |
+RectangleUpdateDecoder::Core::Core( |
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
scoped_refptr<FrameConsumerProxy> consumer) |
@@ -85,13 +154,13 @@ RectangleUpdateDecoder::RectangleUpdateDecoder( |
latest_sequence_number_(0) { |
} |
-RectangleUpdateDecoder::~RectangleUpdateDecoder() { |
+RectangleUpdateDecoder::Core::~Core() { |
} |
-void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
+void RectangleUpdateDecoder::Core::Initialize(const SessionConfig& config) { |
if (!decode_task_runner_->BelongsToCurrentThread()) { |
Wez
2014/01/14 16:23:14
Since RUD runs on main thread and RUD::Core on dec
Sergey Ulanov
2014/01/15 00:58:17
Done.
|
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::Initialize, this, |
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::Core::Initialize, this, |
config)); |
return; |
} |
@@ -115,7 +184,7 @@ void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
} |
} |
-void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, |
+void RectangleUpdateDecoder::Core::DecodePacket(scoped_ptr<VideoPacket> packet, |
const base::Closure& done) { |
DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
@@ -160,15 +229,15 @@ void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, |
} |
} |
-void RectangleUpdateDecoder::SchedulePaint() { |
+void RectangleUpdateDecoder::Core::SchedulePaint() { |
if (paint_scheduled_) |
return; |
paint_scheduled_ = true; |
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::DoPaint, this)); |
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::Core::DoPaint, this)); |
} |
-void RectangleUpdateDecoder::DoPaint() { |
+void RectangleUpdateDecoder::Core::DoPaint() { |
DCHECK(paint_scheduled_); |
paint_scheduled_ = false; |
@@ -184,9 +253,7 @@ void RectangleUpdateDecoder::DoPaint() { |
webrtc::DesktopFrame* buffer = buffers_.front(); |
webrtc::DesktopRegion output_region; |
decoder_->RenderFrame(view_size_, clip_area_, |
- buffer->data(), |
- buffer->stride(), |
- &output_region); |
+ buffer->data(), buffer->stride(), &output_region); |
// Notify the consumer that painting is done. |
if (!output_region.is_empty()) { |
@@ -195,11 +262,12 @@ void RectangleUpdateDecoder::DoPaint() { |
} |
} |
-void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { |
+void RectangleUpdateDecoder::Core::RequestReturnBuffers( |
+ const base::Closure& done) { |
if (!decode_task_runner_->BelongsToCurrentThread()) { |
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::RequestReturnBuffers, |
- this, done)); |
+ FROM_HERE, base::Bind( |
+ &RectangleUpdateDecoder::Core::RequestReturnBuffers, this, done)); |
return; |
} |
@@ -212,10 +280,10 @@ void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { |
done.Run(); |
} |
-void RectangleUpdateDecoder::DrawBuffer(webrtc::DesktopFrame* buffer) { |
+void RectangleUpdateDecoder::Core::DrawBuffer(webrtc::DesktopFrame* buffer) { |
if (!decode_task_runner_->BelongsToCurrentThread()) { |
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::DrawBuffer, |
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::Core::DrawBuffer, |
this, buffer)); |
return; |
} |
@@ -227,11 +295,11 @@ void RectangleUpdateDecoder::DrawBuffer(webrtc::DesktopFrame* buffer) { |
SchedulePaint(); |
} |
-void RectangleUpdateDecoder::InvalidateRegion( |
+void RectangleUpdateDecoder::Core::InvalidateRegion( |
const webrtc::DesktopRegion& region) { |
if (!decode_task_runner_->BelongsToCurrentThread()) { |
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::InvalidateRegion, |
+ FROM_HERE, base::Bind(&RectangleUpdateDecoder::Core::InvalidateRegion, |
this, region)); |
return; |
} |
@@ -242,13 +310,14 @@ void RectangleUpdateDecoder::InvalidateRegion( |
} |
} |
-void RectangleUpdateDecoder::SetOutputSizeAndClip( |
+void RectangleUpdateDecoder::Core::SetOutputSizeAndClip( |
const webrtc::DesktopSize& view_size, |
const webrtc::DesktopRect& clip_area) { |
if (!decode_task_runner_->BelongsToCurrentThread()) { |
decode_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSizeAndClip, |
- this, view_size, clip_area)); |
+ FROM_HERE, |
+ base::Bind(&RectangleUpdateDecoder::Core::SetOutputSizeAndClip, |
+ this, view_size, clip_area)); |
return; |
} |
@@ -281,12 +350,13 @@ void RectangleUpdateDecoder::SetOutputSizeAndClip( |
} |
} |
-const webrtc::DesktopRegion* RectangleUpdateDecoder::GetBufferShape() { |
+const webrtc::DesktopRegion* RectangleUpdateDecoder::Core::GetBufferShape() { |
return decoder_->GetImageShape(); |
} |
-void RectangleUpdateDecoder::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
- const base::Closure& done) { |
+void RectangleUpdateDecoder::Core::ProcessVideoPacket( |
+ scoped_ptr<VideoPacket> packet, |
+ const base::Closure& done) { |
DCHECK(main_task_runner_->BelongsToCurrentThread()); |
// If the video packet is empty then drop it. Empty packets are used to |
@@ -318,18 +388,18 @@ void RectangleUpdateDecoder::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
base::Time decode_start = base::Time::Now(); |
base::Closure decode_done = base::Bind( |
- &RectangleUpdateDecoder::OnPacketDone, this, decode_start, done); |
+ &RectangleUpdateDecoder::Core::OnPacketDone, this, decode_start, done); |
Wez
2014/01/14 16:23:14
You can put all this code in RectangleUpdateDecode
Sergey Ulanov
2014/01/15 00:58:17
Done.
|
decode_task_runner_->PostTask(FROM_HERE, base::Bind( |
- &RectangleUpdateDecoder::DecodePacket, this, |
+ &RectangleUpdateDecoder::Core::DecodePacket, this, |
base::Passed(&packet), decode_done)); |
} |
-void RectangleUpdateDecoder::OnPacketDone(base::Time decode_start, |
- const base::Closure& done) { |
+void RectangleUpdateDecoder::Core::OnPacketDone(base::Time decode_start, |
+ const base::Closure& done) { |
if (!main_task_runner_->BelongsToCurrentThread()) { |
Wez
2014/01/14 16:23:14
Since this method just thread-hops back to |main_t
Sergey Ulanov
2014/01/15 00:58:17
Done.
|
main_task_runner_->PostTask(FROM_HERE, base::Bind( |
- &RectangleUpdateDecoder::OnPacketDone, this, |
+ &RectangleUpdateDecoder::Core::OnPacketDone, this, |
decode_start, done)); |
return; |
} |
@@ -341,9 +411,53 @@ void RectangleUpdateDecoder::OnPacketDone(base::Time decode_start, |
done.Run(); |
} |
-ChromotingStats* RectangleUpdateDecoder::GetStats() { |
+ChromotingStats* RectangleUpdateDecoder::Core::GetStats() { |
DCHECK(main_task_runner_->BelongsToCurrentThread()); |
return &stats_; |
} |
+RectangleUpdateDecoder::RectangleUpdateDecoder( |
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
+ scoped_refptr<FrameConsumerProxy> consumer) |
+ : core_(new Core(main_task_runner, decode_task_runner, consumer)) { |
+} |
+ |
+void RectangleUpdateDecoder::Initialize(const protocol::SessionConfig& config) { |
+ core_->Initialize(config); |
+} |
+ |
+ChromotingStats* RectangleUpdateDecoder::GetStats() { |
+ return core_->GetStats(); |
+} |
+ |
+void RectangleUpdateDecoder::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, |
+ const base::Closure& done) { |
+ core_->ProcessVideoPacket(packet.Pass(), done); |
Wez
2014/01/14 16:23:14
As with Initialize, where we're just proxying call
Sergey Ulanov
2014/01/15 00:58:17
Done.
|
+} |
+ |
+void RectangleUpdateDecoder::DrawBuffer(webrtc::DesktopFrame* buffer) { |
+ core_->DrawBuffer(buffer); |
+} |
+ |
+void RectangleUpdateDecoder::InvalidateRegion( |
+ const webrtc::DesktopRegion& region) { |
+ core_->InvalidateRegion(region); |
+} |
+ |
+void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { |
+ core_->RequestReturnBuffers(done); |
+} |
+ |
+void RectangleUpdateDecoder::SetOutputSizeAndClip( |
+ const webrtc::DesktopSize& view_size, |
+ const webrtc::DesktopRect& clip_area) { |
+ core_->SetOutputSizeAndClip(view_size, clip_area); |
+} |
+ |
+const webrtc::DesktopRegion* RectangleUpdateDecoder::GetBufferShape() { |
+ return core_->GetBufferShape(); |
+} |
+ |
+ |
} // namespace remoting |