diff options
author | kxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-24 21:55:06 +0000 |
---|---|---|
committer | kxing@chromium.org <kxing@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-24 21:55:06 +0000 |
commit | 0cc246139d02e266ce81f6c8895f295ccf1c5438 (patch) | |
tree | be4d09c200d210d8b8b00045c19dff8dcab31f77 /remoting/client | |
parent | e28bcda6365ef544a123fc91d22420a775886cde (diff) | |
download | chromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.zip chromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.tar.gz chromium_src-0cc246139d02e266ce81f6c8895f295ccf1c5438.tar.bz2 |
Moved video stub implementation to RectangleUpdateDecoder.
Review URL: https://chromiumcodereview.appspot.com/10867039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@153305 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/client')
-rw-r--r-- | remoting/client/chromoting_client.cc | 110 | ||||
-rw-r--r-- | remoting/client/chromoting_client.h | 39 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 5 | ||||
-rw-r--r-- | remoting/client/rectangle_update_decoder.cc | 154 | ||||
-rw-r--r-- | remoting/client/rectangle_update_decoder.h | 73 |
5 files changed, 206 insertions, 175 deletions
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc index 7c05d83..3bdc7b6 100644 --- a/remoting/client/chromoting_client.cc +++ b/remoting/client/chromoting_client.cc @@ -22,14 +22,6 @@ namespace remoting { using protocol::AuthenticationMethod; -ChromotingClient::QueuedVideoPacket::QueuedVideoPacket( - scoped_ptr<VideoPacket> packet, const base::Closure& done) - : packet(packet.release()), done(done) { -} - -ChromotingClient::QueuedVideoPacket::~QueuedVideoPacket() { -} - ChromotingClient::ChromotingClient( const ClientConfig& config, ClientContext* client_context, @@ -42,8 +34,6 @@ ChromotingClient::ChromotingClient( connection_(connection), user_interface_(user_interface), rectangle_decoder_(rectangle_decoder), - packet_being_processed_(false), - last_sequence_number_(0), weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { audio_decode_scheduler_.reset(new AudioDecodeScheduler( client_context->main_task_runner(), @@ -69,7 +59,8 @@ void ChromotingClient::Start( connection_->Connect(xmpp_proxy, config_.local_jid, config_.host_jid, config_.host_public_key, transport_factory.Pass(), - authenticator.Pass(), this, this, this, this, + authenticator.Pass(), this, this, this, + rectangle_decoder_, audio_decode_scheduler_.get()); } @@ -77,11 +68,7 @@ void ChromotingClient::Stop(const base::Closure& shutdown_task) { DCHECK(task_runner_->BelongsToCurrentThread()); // Drop all pending packets. - while(!received_packets_.empty()) { - delete received_packets_.front().packet; - received_packets_.front().done.Run(); - received_packets_.pop_front(); - } + rectangle_decoder_->DropAllPackets(); connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected, weak_ptr_, shutdown_task)); @@ -93,7 +80,7 @@ void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) { ChromotingStats* ChromotingClient::GetStats() { DCHECK(task_runner_->BelongsToCurrentThread()); - return &stats_; + return rectangle_decoder_->GetStats(); } void ChromotingClient::InjectClipboardEvent( @@ -107,70 +94,6 @@ void ChromotingClient::SetCursorShape( user_interface_->GetCursorShapeStub()->SetCursorShape(cursor_shape); } -void ChromotingClient::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, - const base::Closure& done) { - DCHECK(task_runner_->BelongsToCurrentThread()); - - // If the video packet is empty then drop it. Empty packets are used to - // maintain activity on the network. - if (!packet->has_data() || packet->data().size() == 0) { - done.Run(); - return; - } - - // Add one frame to the counter. - stats_.video_frame_rate()->Record(1); - - // Record other statistics received from host. - stats_.video_bandwidth()->Record(packet->data().size()); - if (packet->has_capture_time_ms()) - stats_.video_capture_ms()->Record(packet->capture_time_ms()); - if (packet->has_encode_time_ms()) - stats_.video_encode_ms()->Record(packet->encode_time_ms()); - if (packet->has_client_sequence_number() && - packet->client_sequence_number() > last_sequence_number_) { - last_sequence_number_ = packet->client_sequence_number(); - base::TimeDelta round_trip_latency = - base::Time::Now() - - base::Time::FromInternalValue(packet->client_sequence_number()); - stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); - } - - received_packets_.push_back(QueuedVideoPacket(packet.Pass(), done)); - if (!packet_being_processed_) - DispatchPacket(); -} - -int ChromotingClient::GetPendingVideoPackets() { - DCHECK(task_runner_->BelongsToCurrentThread()); - return received_packets_.size(); -} - -void ChromotingClient::DispatchPacket() { - DCHECK(task_runner_->BelongsToCurrentThread()); - CHECK(!packet_being_processed_); - - if (received_packets_.empty()) { - // Nothing to do! - return; - } - - scoped_ptr<VideoPacket> packet(received_packets_.front().packet); - received_packets_.front().packet = NULL; - packet_being_processed_ = true; - - // Measure the latency between the last packet being received and presented. - bool last_packet = (packet->flags() & VideoPacket::LAST_PACKET) != 0; - base::Time decode_start; - if (last_packet) - decode_start = base::Time::Now(); - - rectangle_decoder_->DecodePacket( - packet.Pass(), - base::Bind(&ChromotingClient::OnPacketDone, base::Unretained(this), - last_packet, decode_start)); -} - void ChromotingClient::OnConnectionState( protocol::ConnectionToHost::State state, protocol::ErrorCode error) { @@ -186,31 +109,6 @@ void ChromotingClient::OnConnectionReady(bool ready) { user_interface_->OnConnectionReady(ready); } -void ChromotingClient::OnPacketDone(bool last_packet, - base::Time decode_start) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask(FROM_HERE, base::Bind( - &ChromotingClient::OnPacketDone, base::Unretained(this), - last_packet, decode_start)); - return; - } - - // Record the latency between the final packet being received and - // presented. - if (last_packet) { - stats_.video_decode_ms()->Record( - (base::Time::Now() - decode_start).InMilliseconds()); - } - - received_packets_.front().done.Run(); - received_packets_.pop_front(); - - packet_being_processed_ = false; - - // Process the next video packet. - DispatchPacket(); -} - void ChromotingClient::Initialize() { DCHECK(task_runner_->BelongsToCurrentThread()); diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h index f2355f1..f826394 100644 --- a/remoting/client/chromoting_client.h +++ b/remoting/client/chromoting_client.h @@ -38,10 +38,8 @@ class ClientContext; class ClientUserInterface; class RectangleUpdateDecoder; -// TODO(sergeyu): Move VideoStub implementation to RectangleUpdateDecoder. class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, - public protocol::ClientStub, - public protocol::VideoStub { + public protocol::ClientStub { public: // Objects passed in are not owned by this class. ChromotingClient(const ClientConfig& config, @@ -75,32 +73,10 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, protocol::ErrorCode error) OVERRIDE; virtual void OnConnectionReady(bool ready) OVERRIDE; - // VideoStub implementation. - virtual void ProcessVideoPacket(scoped_ptr<VideoPacket> packet, - const base::Closure& done) OVERRIDE; - virtual int GetPendingVideoPackets() OVERRIDE; - private: - struct QueuedVideoPacket { - QueuedVideoPacket(scoped_ptr<VideoPacket> packet, - const base::Closure& done); - ~QueuedVideoPacket(); - VideoPacket* packet; - base::Closure done; - }; - // Initializes connection. void Initialize(); - // If a packet is not being processed, dispatches a single message from the - // |received_packets_| queue. - void DispatchPacket(); - - // Callback method when a VideoPacket is processed. - // If |last_packet| is true then |decode_start| contains the timestamp when - // the packet will start to be processed. - void OnPacketDone(bool last_packet, base::Time decode_start); - void OnDisconnected(const base::Closure& shutdown_task); // The following are not owned by this class. @@ -116,22 +92,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, // If non-NULL, this is called when the client is done. base::Closure client_done_; - // Contains all video packets that have been received, but have not yet been - // processed. - // - // Used to serialize sending of messages to the client. - std::list<QueuedVideoPacket> received_packets_; - - // True if a message is being processed. Can be used to determine if it is - // safe to dispatch another message. - bool packet_being_processed_; - // Record the statistics of the connection. ChromotingStats stats_; - // Keep track of the last sequence number bounced back from the host. - int64 last_sequence_number_; - // WeakPtr used to avoid tasks accessing the client after it is deleted. base::WeakPtrFactory<ChromotingClient> weak_factory_; base::WeakPtr<ChromotingClient> weak_ptr_; diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index f4be000..a28a8e9 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -232,8 +232,9 @@ bool ChromotingInstance::Init(uint32_t argc, // PepperView with a ref-counted proxy object. scoped_refptr<FrameConsumerProxy> consumer_proxy = new FrameConsumerProxy(plugin_task_runner_); - rectangle_decoder_ = new RectangleUpdateDecoder( - context_.decode_task_runner(), consumer_proxy); + rectangle_decoder_ = new RectangleUpdateDecoder(context_.main_task_runner(), + context_.decode_task_runner(), + consumer_proxy); view_.reset(new PepperView(this, &context_, rectangle_decoder_.get())); consumer_proxy->Attach(view_->AsWeakPtr()); diff --git a/remoting/client/rectangle_update_decoder.cc b/remoting/client/rectangle_update_decoder.cc index 0fb253b..c7a1404 100644 --- a/remoting/client/rectangle_update_decoder.cc +++ b/remoting/client/rectangle_update_decoder.cc @@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/callback.h" #include "base/location.h" #include "base/logging.h" #include "base/message_loop_proxy.h" @@ -24,16 +23,30 @@ using remoting::protocol::SessionConfig; namespace remoting { +RectangleUpdateDecoder::QueuedVideoPacket::QueuedVideoPacket( + scoped_ptr<VideoPacket> packet, + const base::Closure& done) + : packet(packet.release()), + done(done) { +} + +RectangleUpdateDecoder::QueuedVideoPacket::~QueuedVideoPacket() { +} + RectangleUpdateDecoder::RectangleUpdateDecoder( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, scoped_refptr<FrameConsumerProxy> consumer) - : task_runner_(task_runner), + : main_task_runner_(main_task_runner), + decode_task_runner_(decode_task_runner), consumer_(consumer), source_size_(SkISize::Make(0, 0)), source_dpi_(SkIPoint::Make(0, 0)), view_size_(SkISize::Make(0, 0)), clip_area_(SkIRect::MakeEmpty()), - paint_scheduled_(false) { + paint_scheduled_(false), + packet_being_processed_(false), + latest_sequence_number_(0) { } RectangleUpdateDecoder::~RectangleUpdateDecoder() { @@ -55,12 +68,7 @@ void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, const base::Closure& done) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( - FROM_HERE, base::Bind(&RectangleUpdateDecoder::DecodePacket, - this, base::Passed(&packet), done)); - return; - } + DCHECK(decode_task_runner_->BelongsToCurrentThread()); base::ScopedClosureRunner done_runner(done); bool decoder_needs_reset = false; @@ -109,7 +117,7 @@ void RectangleUpdateDecoder::SchedulePaint() { if (paint_scheduled_) return; paint_scheduled_ = true; - task_runner_->PostTask( + decode_task_runner_->PostTask( FROM_HERE, base::Bind(&RectangleUpdateDecoder::DoPaint, this)); } @@ -141,8 +149,8 @@ void RectangleUpdateDecoder::DoPaint() { } void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( + if (!decode_task_runner_->BelongsToCurrentThread()) { + decode_task_runner_->PostTask( FROM_HERE, base::Bind(&RectangleUpdateDecoder::RequestReturnBuffers, this, done)); return; @@ -158,8 +166,8 @@ void RectangleUpdateDecoder::RequestReturnBuffers(const base::Closure& done) { } void RectangleUpdateDecoder::DrawBuffer(pp::ImageData* buffer) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( + if (!decode_task_runner_->BelongsToCurrentThread()) { + decode_task_runner_->PostTask( FROM_HERE, base::Bind(&RectangleUpdateDecoder::DrawBuffer, this, buffer)); return; @@ -173,8 +181,8 @@ void RectangleUpdateDecoder::DrawBuffer(pp::ImageData* buffer) { } void RectangleUpdateDecoder::InvalidateRegion(const SkRegion& region) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( + if (!decode_task_runner_->BelongsToCurrentThread()) { + decode_task_runner_->PostTask( FROM_HERE, base::Bind(&RectangleUpdateDecoder::InvalidateRegion, this, region)); return; @@ -188,8 +196,8 @@ void RectangleUpdateDecoder::InvalidateRegion(const SkRegion& region) { void RectangleUpdateDecoder::SetOutputSizeAndClip(const SkISize& view_size, const SkIRect& clip_area) { - if (!task_runner_->BelongsToCurrentThread()) { - task_runner_->PostTask( + if (!decode_task_runner_->BelongsToCurrentThread()) { + decode_task_runner_->PostTask( FROM_HERE, base::Bind(&RectangleUpdateDecoder::SetOutputSizeAndClip, this, view_size, clip_area)); return; @@ -225,4 +233,112 @@ void RectangleUpdateDecoder::SetOutputSizeAndClip(const SkISize& view_size, } } +void RectangleUpdateDecoder::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 + // maintain activity on the network. + if (!packet->has_data() || packet->data().size() == 0) { + done.Run(); + return; + } + + // Add one frame to the counter. + stats_.video_frame_rate()->Record(1); + + // Record other statistics received from host. + stats_.video_bandwidth()->Record(packet->data().size()); + if (packet->has_capture_time_ms()) + stats_.video_capture_ms()->Record(packet->capture_time_ms()); + if (packet->has_encode_time_ms()) + stats_.video_encode_ms()->Record(packet->encode_time_ms()); + if (packet->has_client_sequence_number() && + packet->client_sequence_number() > latest_sequence_number_) { + latest_sequence_number_ = packet->client_sequence_number(); + base::TimeDelta round_trip_latency = + base::Time::Now() - + base::Time::FromInternalValue(packet->client_sequence_number()); + stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); + } + + received_packets_.push_back(QueuedVideoPacket(packet.Pass(), done)); + if (!packet_being_processed_) + ProcessNextPacket(); +} + +int RectangleUpdateDecoder::GetPendingVideoPackets() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return received_packets_.size(); +} + +void RectangleUpdateDecoder::DropAllPackets() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + + while(!received_packets_.empty()) { + delete received_packets_.front().packet; + received_packets_.front().done.Run(); + received_packets_.pop_front(); + } +} + +void RectangleUpdateDecoder::ProcessNextPacket() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + CHECK(!packet_being_processed_); + + if (received_packets_.empty()) { + // Nothing to do! + return; + } + + scoped_ptr<VideoPacket> packet(received_packets_.front().packet); + received_packets_.front().packet = NULL; + packet_being_processed_ = true; + + // Measure the latency between the last packet being received and presented. + bool last_packet = (packet->flags() & VideoPacket::LAST_PACKET) != 0; + base::Time decode_start; + if (last_packet) + decode_start = base::Time::Now(); + + base::Closure callback = base::Bind(&RectangleUpdateDecoder::OnPacketDone, + this, + last_packet, + decode_start); + + decode_task_runner_->PostTask(FROM_HERE, base::Bind( + &RectangleUpdateDecoder::DecodePacket, this, + base::Passed(&packet), callback)); +} + +void RectangleUpdateDecoder::OnPacketDone(bool last_packet, + base::Time decode_start) { + if (!main_task_runner_->BelongsToCurrentThread()) { + main_task_runner_->PostTask(FROM_HERE, base::Bind( + &RectangleUpdateDecoder::OnPacketDone, this, + last_packet, decode_start)); + return; + } + + // Record the latency between the final packet being received and + // presented. + if (last_packet) { + stats_.video_decode_ms()->Record( + (base::Time::Now() - decode_start).InMilliseconds()); + } + + received_packets_.front().done.Run(); + received_packets_.pop_front(); + + packet_being_processed_ = false; + + // Process the next video packet. + ProcessNextPacket(); +} + +ChromotingStats* RectangleUpdateDecoder::GetStats() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return &stats_; +} + } // namespace remoting diff --git a/remoting/client/rectangle_update_decoder.h b/remoting/client/rectangle_update_decoder.h index 3d61b97..af91267 100644 --- a/remoting/client/rectangle_update_decoder.h +++ b/remoting/client/rectangle_update_decoder.h @@ -7,12 +7,14 @@ #include <list> -#include "base/callback_forward.h" +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "remoting/codec/video_decoder.h" +#include "remoting/client/chromoting_stats.h" #include "remoting/client/frame_consumer_proxy.h" #include "remoting/client/frame_producer.h" +#include "remoting/protocol/video_stub.h" namespace base { class SingleThreadTaskRunner; @@ -24,6 +26,7 @@ class ImageData; namespace remoting { +class ChromotingStats; class VideoPacket; namespace protocol { @@ -35,21 +38,24 @@ class SessionConfig; // TODO(sergeyu): Rename this class. class RectangleUpdateDecoder : public base::RefCountedThreadSafe<RectangleUpdateDecoder>, - public FrameProducer { + public FrameProducer, + public protocol::VideoStub { public: - // Creates an update decoder on |task_runner_|, outputting to |consumer|. + // Creates an update decoder on |main_task_runner_| and |decode_task_runner_|, + // outputting to |consumer|. The |main_task_runner_| is responsible for + // receiving and queueing packets. The |decode_task_runner_| is responsible + // for decoding the video packets. // TODO(wez): Replace the ref-counted proxy with an owned FrameConsumer. RectangleUpdateDecoder( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, scoped_refptr<FrameConsumerProxy> consumer); // Initializes decoder with the information from the protocol config. void Initialize(const protocol::SessionConfig& config); - // 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); + // Removes all video packets in the queue. + void DropAllPackets(); // FrameProducer implementation. These methods may be called before we are // Initialize()d, or we know the source screen size. @@ -59,7 +65,23 @@ class RectangleUpdateDecoder virtual void SetOutputSizeAndClip(const SkISize& view_size, const SkIRect& clip_area) OVERRIDE; + // VideoStub implementation. + virtual void ProcessVideoPacket(scoped_ptr<VideoPacket> packet, + const base::Closure& done) OVERRIDE; + virtual int GetPendingVideoPackets() OVERRIDE; + + // Return the stats recorded by this client. + ChromotingStats* GetStats(); + private: + struct QueuedVideoPacket { + QueuedVideoPacket(scoped_ptr<VideoPacket> packet, + const base::Closure& done); + ~QueuedVideoPacket(); + VideoPacket* packet; + base::Closure done; + }; + friend class base::RefCountedThreadSafe<RectangleUpdateDecoder>; virtual ~RectangleUpdateDecoder(); @@ -68,7 +90,22 @@ class RectangleUpdateDecoder void SchedulePaint(); void DoPaint(); - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + // If a packet is not being processed, dispatches a single message from the + // |received_packets_| queue. + void ProcessNextPacket(); + + // 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. + // If |last_packet| is true then |decode_start| contains the timestamp when + // the packet will start to be processed. + void OnPacketDone(bool last_packet, base::Time decode_start); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_; scoped_refptr<FrameConsumerProxy> consumer_; scoped_ptr<VideoDecoder> decoder_; @@ -78,7 +115,7 @@ class RectangleUpdateDecoder // Vertical and horizontal DPI of the remote screen. SkIPoint source_dpi_; - // The current dimentions of the frame consumer view. + // The current dimensions of the frame consumer view. SkISize view_size_; SkIRect clip_area_; @@ -87,6 +124,22 @@ class RectangleUpdateDecoder // Flag used to coalesce runs of SchedulePaint()s into a single DoPaint(). bool paint_scheduled_; + + // Contains all video packets that have been received, but have not yet been + // processed. + // + // Used to serialize sending of messages to the client. + // TODO(sergeyu): Simplify this code and remove this list. + std::list<QueuedVideoPacket> received_packets_; + + // True if a message is being processed. Can be used to determine if it is + // safe to dispatch another message. + bool packet_being_processed_; + + ChromotingStats stats_; + + // Keep track of the most recent sequence number bounced back from the host. + int64 latest_sequence_number_; }; } // namespace remoting |