diff options
Diffstat (limited to 'remoting/host')
-rw-r--r-- | remoting/host/client_connection.cc | 21 | ||||
-rw-r--r-- | remoting/host/client_connection.h | 17 | ||||
-rw-r--r-- | remoting/host/client_connection_unittest.cc | 17 | ||||
-rw-r--r-- | remoting/host/encoder.h | 12 | ||||
-rw-r--r-- | remoting/host/encoder_verbatim.cc | 45 | ||||
-rw-r--r-- | remoting/host/encoder_verbatim.h | 8 | ||||
-rw-r--r-- | remoting/host/mock_objects.h | 5 | ||||
-rw-r--r-- | remoting/host/session_manager.cc | 29 | ||||
-rw-r--r-- | remoting/host/session_manager.h | 6 | ||||
-rw-r--r-- | remoting/host/session_manager_unittest.cc | 19 |
10 files changed, 83 insertions, 96 deletions
diff --git a/remoting/host/client_connection.cc b/remoting/host/client_connection.cc index d69a326..6c8516a 100644 --- a/remoting/host/client_connection.cc +++ b/remoting/host/client_connection.cc @@ -35,6 +35,16 @@ ClientConnection::~ClientConnection() { // jingle channel. } +// static +scoped_refptr<media::DataBuffer> + ClientConnection::CreateWireFormatDataBuffer( + const HostMessage* msg) { + // TODO(hclam): Instead of serializing |msg| create an DataBuffer + // object that wraps around it. + scoped_ptr<const HostMessage> message_deleter(msg); + return SerializeAndFrameMessage(*msg); +} + void ClientConnection::SendInitClientMessage(int width, int height) { DCHECK_EQ(loop_, MessageLoop::current()); DCHECK(!update_stream_size_); @@ -68,7 +78,6 @@ void ClientConnection::SendBeginUpdateStreamMessage() { } void ClientConnection::SendUpdateStreamPacketMessage( - const UpdateStreamPacketHeader* header, scoped_refptr<DataBuffer> data) { DCHECK_EQ(loop_, MessageLoop::current()); @@ -76,16 +85,8 @@ void ClientConnection::SendUpdateStreamPacketMessage( if (!channel_) return; - HostMessage msg; - msg.mutable_update_stream_packet()->mutable_header()->CopyFrom(*header); - // TODO(hclam): This introduce one memory copy. Eliminate it. - msg.mutable_update_stream_packet()->set_data( - data->GetData(), data->GetDataSize()); - DCHECK(msg.IsInitialized()); - - scoped_refptr<DataBuffer> encoded_data = SerializeAndFrameMessage(msg); update_stream_size_ += data->GetDataSize(); - channel_->Write(encoded_data); + channel_->Write(data); } void ClientConnection::SendEndUpdateStreamMessage() { diff --git a/remoting/host/client_connection.h b/remoting/host/client_connection.h index 3e85cc9..c647eb6 100644 --- a/remoting/host/client_connection.h +++ b/remoting/host/client_connection.h @@ -62,6 +62,12 @@ class ClientConnection : public base::RefCountedThreadSafe<ClientConnection>, virtual ~ClientConnection(); + // Creates a DataBuffer object that wraps around HostMessage. The DataBuffer + // object will be responsible for serializing and framing the message. + // DataBuffer will also own |msg| after this call. + static scoped_refptr<media::DataBuffer> CreateWireFormatDataBuffer( + const HostMessage* msg); + virtual void set_jingle_channel(JingleChannel* channel) { channel_ = channel; } @@ -75,10 +81,15 @@ class ClientConnection : public base::RefCountedThreadSafe<ClientConnection>, // Notifies the viewer the start of an update stream. virtual void SendBeginUpdateStreamMessage(); - // Send encoded update stream data to the viewer. The viewer - // should not take ownership of the data. + // Send encoded update stream data to the viewer. + // + // |data| is the actual bytes in wire format. That means it is fully framed + // and serialized from a HostMessage. This is a special case only for + // UpdateStreamPacket to reduce the amount of memory copies. + // + // |data| should be created by calling to + // CreateWireFormatDataBuffer(HostMessage). virtual void SendUpdateStreamPacketMessage( - const UpdateStreamPacketHeader* header, scoped_refptr<media::DataBuffer> data); // Notifies the viewer the update stream has ended. diff --git a/remoting/host/client_connection_unittest.cc b/remoting/host/client_connection_unittest.cc index b7cb10c..9c3bcb3 100644 --- a/remoting/host/client_connection_unittest.cc +++ b/remoting/host/client_connection_unittest.cc @@ -55,14 +55,8 @@ TEST_F(ClientConnectionTest, SendUpdateStream) { // Then send the actual data. EXPECT_CALL(*channel_, Write(_)); - scoped_ptr<UpdateStreamPacketHeader> header(new UpdateStreamPacketHeader); - header->set_x(0); - header->set_y(0); - header->set_width(640); - header->set_height(480); - scoped_refptr<media::DataBuffer> data = new media::DataBuffer(10); - viewer_->SendUpdateStreamPacketMessage(header.get(), data); + viewer_->SendUpdateStreamPacketMessage(data); // Send the end of update message. EXPECT_CALL(*channel_, Write(_)); @@ -105,15 +99,8 @@ TEST_F(ClientConnectionTest, Close) { EXPECT_CALL(*channel_, Close()); viewer_->Disconnect(); - viewer_->SendBeginUpdateStreamMessage(); - scoped_ptr<UpdateStreamPacketHeader> header(new UpdateStreamPacketHeader); - header->set_x(0); - header->set_y(0); - header->set_width(640); - header->set_height(480); - scoped_refptr<media::DataBuffer> data = new media::DataBuffer(10); - viewer_->SendUpdateStreamPacketMessage(header.get(), data); + viewer_->SendUpdateStreamPacketMessage(data); viewer_->SendEndUpdateStreamMessage(); viewer_->Disconnect(); } diff --git a/remoting/host/encoder.h b/remoting/host/encoder.h index 09cbdde..ee43c94 100644 --- a/remoting/host/encoder.h +++ b/remoting/host/encoder.h @@ -17,6 +17,8 @@ namespace media { namespace remoting { +class HostMessage; + // A class to perform the task of encoding a continous stream of // images. // This class operates asynchronously to enable maximum throughput. @@ -34,11 +36,11 @@ class Encoder { typedef int EncodingState; // DataAvailableCallback is called as blocks of data are made available - // from the encoder. The callback takes ownership of header and is - // responsible for deleting it. - typedef Callback3<const UpdateStreamPacketHeader*, - const scoped_refptr<media::DataBuffer>&, - EncodingState>::Type DataAvailableCallback; + // from the encoder. Data made available by the encoder is in the form + // of HostMessage to reduce the amount of memory copies. + // The callback takes ownership of the HostMessage and is responsible for + // deleting it. + typedef Callback2<HostMessage*, EncodingState>::Type DataAvailableCallback; virtual ~Encoder() {} diff --git a/remoting/host/encoder_verbatim.cc b/remoting/host/encoder_verbatim.cc index f1e2b46..fd9dadf 100644 --- a/remoting/host/encoder_verbatim.cc +++ b/remoting/host/encoder_verbatim.cc @@ -7,6 +7,7 @@ #include "gfx/rect.h" #include "media/base/data_buffer.h" #include "remoting/base/protocol_util.h" +#include "remoting/base/protocol/chromotocol.pb.h" namespace remoting { @@ -17,13 +18,14 @@ void EncoderVerbatim::Encode(scoped_refptr<Capturer::CaptureData> capture_data, DataAvailableCallback* data_available_callback) { int num_rects = capture_data->dirty_rects().size(); for (int i = 0; i < num_rects; i++) { - scoped_refptr<DataBuffer> data; const gfx::Rect& dirty_rect = capture_data->dirty_rects()[i]; - scoped_ptr<UpdateStreamPacketHeader> header(new UpdateStreamPacketHeader); - if (EncodeRect(dirty_rect, - capture_data, - header.get(), - &data)) { + HostMessage* msg = new HostMessage(); + UpdateStreamPacketMessage* packet = msg->mutable_update_stream_packet(); + + if (EncodeRect(dirty_rect, capture_data, packet)) { + // Prepare the end rect content. + packet->mutable_end_rect(); + EncodingState state = EncodingInProgress; if (i == 0) { state |= EncodingStarting; @@ -31,9 +33,7 @@ void EncoderVerbatim::Encode(scoped_refptr<Capturer::CaptureData> capture_data, if (i == num_rects - 1) { state |= EncodingEnded; } - data_available_callback->Run(header.release(), - data, - state); + data_available_callback->Run(msg, state); } } @@ -43,12 +43,18 @@ void EncoderVerbatim::Encode(scoped_refptr<Capturer::CaptureData> capture_data, bool EncoderVerbatim::EncodeRect( const gfx::Rect& dirty, const scoped_refptr<Capturer::CaptureData>& capture_data, - UpdateStreamPacketHeader* header, - scoped_refptr<DataBuffer>* output_data) { - int bytes_per_pixel = GetBytesPerPixel(capture_data->pixel_format()); - int row_size = bytes_per_pixel * dirty.width(); + UpdateStreamPacketMessage* packet) { + // Prepare the begin rect content. + packet->mutable_begin_rect()->set_x(dirty.x()); + packet->mutable_begin_rect()->set_y(dirty.y()); + packet->mutable_begin_rect()->set_width(dirty.width()); + packet->mutable_begin_rect()->set_height(dirty.height()); + packet->mutable_begin_rect()->set_encoding(EncodingNone); + packet->mutable_begin_rect()->set_pixel_format(capture_data->pixel_format()); // Calculate the size of output. + int bytes_per_pixel = GetBytesPerPixel(capture_data->pixel_format()); + int row_size = bytes_per_pixel * dirty.width(); int output_size = 0; for (int i = 0; i < Capturer::DataPlanes::kPlaneCount; ++i) { // TODO(hclam): Handle YUV since the height would be different. @@ -57,15 +63,10 @@ bool EncoderVerbatim::EncodeRect( output_size += row_size * dirty.height(); } - header->set_x(dirty.x()); - header->set_y(dirty.y()); - header->set_width(dirty.width()); - header->set_height(dirty.height()); - header->set_encoding(EncodingNone); - header->set_pixel_format(capture_data->pixel_format()); - - *output_data = new DataBuffer(new uint8[output_size], output_size); - uint8* out = (*output_data)->GetWritableData(); + // Resize the output data buffer. + packet->mutable_rect_data()->mutable_data()->resize(output_size); + uint8* out = reinterpret_cast<uint8*>( + &((*packet->mutable_rect_data()->mutable_data())[0])); for (int i = 0; i < Capturer::DataPlanes::kPlaneCount; ++i) { const uint8* in = capture_data->data_planes().data[i]; diff --git a/remoting/host/encoder_verbatim.h b/remoting/host/encoder_verbatim.h index 745d544..175b954 100644 --- a/remoting/host/encoder_verbatim.h +++ b/remoting/host/encoder_verbatim.h @@ -9,6 +9,8 @@ namespace remoting { +class UpdateStreamPacket; + // EncoderVerbatim implements Encoder and simply copies input to the output // buffer verbatim. class EncoderVerbatim : public Encoder { @@ -21,12 +23,12 @@ class EncoderVerbatim : public Encoder { DataAvailableCallback* data_available_callback); private: - // Encode a single dirty rect. Called by Encode(). + // Encode a single dirty rect. Called by Encode(). Output is written + // to |msg|. // Returns false if there is an error. bool EncodeRect(const gfx::Rect& dirty, const scoped_refptr<Capturer::CaptureData>& capture_data, - UpdateStreamPacketHeader* header, - scoped_refptr<media::DataBuffer>* output_data); + UpdateStreamPacketMessage* msg); }; } // namespace remoting diff --git a/remoting/host/mock_objects.h b/remoting/host/mock_objects.h index 0585864..f4135f2 100644 --- a/remoting/host/mock_objects.h +++ b/remoting/host/mock_objects.h @@ -61,9 +61,8 @@ class MockClientConnection : public ClientConnection { MOCK_METHOD2(SendInitClientMessage, void(int width, int height)); MOCK_METHOD0(SendBeginUpdateStreamMessage, void()); - MOCK_METHOD2(SendUpdateStreamPacketMessage, - void(const UpdateStreamPacketHeader* header, - scoped_refptr<media::DataBuffer> data)); + MOCK_METHOD1(SendUpdateStreamPacketMessage, + void(scoped_refptr<media::DataBuffer> data)); MOCK_METHOD0(SendEndUpdateStreamMessage, void()); MOCK_METHOD0(GetPendingUpdateStreamMessages, int()); diff --git a/remoting/host/session_manager.cc b/remoting/host/session_manager.cc index 8e1dd86..5be8b56d 100644 --- a/remoting/host/session_manager.cc +++ b/remoting/host/session_manager.cc @@ -322,25 +322,26 @@ void SessionManager::DoRateControl() { ScheduleNextRateControl(); } -void SessionManager::DoSendUpdate(const UpdateStreamPacketHeader* header, - const scoped_refptr<media::DataBuffer> data, +void SessionManager::DoSendUpdate(HostMessage* message, Encoder::EncodingState state) { - // Take ownership of header. - scoped_ptr<const UpdateStreamPacketHeader> header_owner(header); DCHECK_EQ(network_loop_, MessageLoop::current()); + // Create a data buffer in wire format from |message|. + scoped_refptr<media::DataBuffer> data = + ClientConnection::CreateWireFormatDataBuffer(message); + for (ClientConnectionList::const_iterator i = clients_.begin(); - i < clients_.end(); - ++i) { + i < clients_.end(); ++i) { + // TODO(hclam): Merge BeginUpdateStreamMessage into |message|. if (state & Encoder::EncodingStarting) { (*i)->SendBeginUpdateStreamMessage(); } - (*i)->SendUpdateStreamPacketMessage(header, data); + (*i)->SendUpdateStreamPacketMessage(data); - if (state & Encoder::EncodingEnded) { + // TODO(hclam): Merge EndUpdateStreamMessage into |message|. + if (state & Encoder::EncodingEnded) (*i)->SendEndUpdateStreamMessage(); - } } } @@ -390,9 +391,7 @@ void SessionManager::DoEncode( } void SessionManager::EncodeDataAvailableTask( - const UpdateStreamPacketHeader *header, - const scoped_refptr<media::DataBuffer>& data, - Encoder::EncodingState state) { + HostMessage* message, Encoder::EncodingState state) { DCHECK_EQ(encode_loop_, MessageLoop::current()); // Before a new encode task starts, notify clients a new update @@ -401,11 +400,7 @@ void SessionManager::EncodeDataAvailableTask( // task. The ownership will eventually pass to the ClientConnections. network_loop_->PostTask( FROM_HERE, - NewRunnableMethod(this, - &SessionManager::DoSendUpdate, - header, - data, - state)); + NewRunnableMethod(this, &SessionManager::DoSendUpdate, message, state)); if (state & Encoder::EncodingEnded) { capture_loop_->PostTask( diff --git a/remoting/host/session_manager.h b/remoting/host/session_manager.h index b56564f..c2a2149 100644 --- a/remoting/host/session_manager.h +++ b/remoting/host/session_manager.h @@ -131,8 +131,7 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> { void DoRateControl(); // DoSendUpdate takes ownership of header and is responsible for deleting it. - void DoSendUpdate(const UpdateStreamPacketHeader* header, - const scoped_refptr<media::DataBuffer> data, + void DoSendUpdate(HostMessage* message, Encoder::EncodingState state); void DoSendInit(scoped_refptr<ClientConnection> client, int width, int height); @@ -147,8 +146,7 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> { // EncodeDataAvailableTask takes ownership of header and is responsible for // deleting it. - void EncodeDataAvailableTask(const UpdateStreamPacketHeader *header, - const scoped_refptr<media::DataBuffer>& data, + void EncodeDataAvailableTask(HostMessage* message, Encoder::EncodingState state); // Message loops used by this class. diff --git a/remoting/host/session_manager_unittest.cc b/remoting/host/session_manager_unittest.cc index 5a4e4eb..e6d8114 100644 --- a/remoting/host/session_manager_unittest.cc +++ b/remoting/host/session_manager_unittest.cc @@ -58,18 +58,11 @@ ACTION_P2(RunCallback, rects, data) { delete arg0; } -ACTION_P3(FinishDecode, rects, buffer, header) { - gfx::Rect& rect = (*rects)[0]; +ACTION_P(FinishEncode, msg) { Encoder::EncodingState state = (Encoder::EncodingStarting | Encoder::EncodingInProgress | Encoder::EncodingEnded); - header->set_x(rect.x()); - header->set_y(rect.y()); - header->set_width(rect.width()); - header->set_height(rect.height()); - header->set_encoding(kEncoding); - header->set_pixel_format(kFormat); - arg2->Run(header, *buffer, state); + arg2->Run(msg, state); } ACTION_P(AssignCaptureData, data) { @@ -111,15 +104,13 @@ TEST_F(SessionManagerTest, OneRecordCycle) { .WillOnce(RunCallback(update_rects, data)); // Expect the encoder be called. - scoped_refptr<media::DataBuffer> buffer = new media::DataBuffer(0); - UpdateStreamPacketHeader *header = new UpdateStreamPacketHeader; + HostMessage* msg = new HostMessage(); EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) - .WillOnce(FinishDecode(&update_rects, &buffer, header)); + .WillOnce(FinishEncode(msg)); // Expect the client be notified. EXPECT_CALL(*client_, SendBeginUpdateStreamMessage()); - - EXPECT_CALL(*client_, SendUpdateStreamPacketMessage(header ,buffer)); + EXPECT_CALL(*client_, SendUpdateStreamPacketMessage(_)); EXPECT_CALL(*client_, SendEndUpdateStreamMessage()); EXPECT_CALL(*client_, GetPendingUpdateStreamMessages()) .Times(AtLeast(0)) |