summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/host/capturer.h10
-rw-r--r--remoting/host/client_connection.cc2
-rw-r--r--remoting/host/client_connection.h2
-rw-r--r--remoting/host/client_connection_unittest.cc6
-rw-r--r--remoting/host/encoder.h28
-rw-r--r--remoting/host/encoder_verbatim.cc40
-rw-r--r--remoting/host/encoder_verbatim.h13
-rw-r--r--remoting/host/mock_objects.h17
-rw-r--r--remoting/host/session_manager.cc92
-rw-r--r--remoting/host/session_manager.h55
-rw-r--r--remoting/host/session_manager_unittest.cc46
11 files changed, 166 insertions, 145 deletions
diff --git a/remoting/host/capturer.h b/remoting/host/capturer.h
index 6007b350..77a8aad 100644
--- a/remoting/host/capturer.h
+++ b/remoting/host/capturer.h
@@ -31,10 +31,10 @@ class Capturer {
// Capture the full screen. When the action is completed |done_task|
// is called.
//
- // It is OK to call this methods while another thread is reading
+ // It is OK to call this method while another thread is reading
// data of the last capture.
// There can be at most one concurrent read going on when this
- // methods is called.
+ // method is called.
virtual void CaptureFullScreen(Task* done_task) = 0;
// Capture the updated regions since last capture. If the last
@@ -45,7 +45,7 @@ class Capturer {
// It is OK to call this method while another thread is reading
// data of the last capture.
// There can be at most one concurrent read going on when this
- // methods is called.
+ // method is called.
virtual void CaptureDirtyRects(Task* done_task) = 0;
// Capture the specified screen rect and call |done_task| when complete.
@@ -55,14 +55,14 @@ class Capturer {
// It is OK to call this method while another thread is reading
// data of the last capture.
// There can be at most one concurrent read going on when this
- // methods is called.
+ // method is called.
virtual void CaptureRect(const gfx::Rect& rect, Task* done_task) = 0;
// Get the image data of the last capture. The pointers to data is
// written to |planes|. |planes| should be an array of 3 elements.
virtual void GetData(const uint8* planes[]) const = 0;
- // Get the image data stride of the last capture. This size of strides
+ // Get the image data stride of the last capture. The size of strides
// is written to |strides|. |strides| should be array of 3 elements.
virtual void GetDataStride(int strides[]) const = 0;
diff --git a/remoting/host/client_connection.cc b/remoting/host/client_connection.cc
index 5bf962c..23b8b80 100644
--- a/remoting/host/client_connection.cc
+++ b/remoting/host/client_connection.cc
@@ -62,7 +62,7 @@ void ClientConnection::SendBeginUpdateStreamMessage() {
}
void ClientConnection::SendUpdateStreamPacketMessage(
- UpdateStreamPacketHeader* header,
+ const UpdateStreamPacketHeader* header,
scoped_refptr<DataBuffer> data) {
DCHECK_EQ(loop_, MessageLoop::current());
DCHECK(channel_.get());
diff --git a/remoting/host/client_connection.h b/remoting/host/client_connection.h
index 4b46ee3..810eb61 100644
--- a/remoting/host/client_connection.h
+++ b/remoting/host/client_connection.h
@@ -78,7 +78,7 @@ class ClientConnection : public base::RefCountedThreadSafe<ClientConnection>,
// Send encoded update stream data to the viewer. The viewer
// should not take ownership of the data.
virtual void SendUpdateStreamPacketMessage(
- UpdateStreamPacketHeader* header,
+ 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 d7be888..f82c887 100644
--- a/remoting/host/client_connection_unittest.cc
+++ b/remoting/host/client_connection_unittest.cc
@@ -51,14 +51,14 @@ TEST_F(ClientConnectionTest, SendUpdateStream) {
// Then send the actual data.
EXPECT_CALL(*channel_, Write(_));
- UpdateStreamPacketHeader* header = new UpdateStreamPacketHeader();
+ 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, data);
- delete header;
+ viewer_->SendUpdateStreamPacketMessage(header.get(), data);
// Send the end of update message.
EXPECT_CALL(*channel_, Write(_));
diff --git a/remoting/host/encoder.h b/remoting/host/encoder.h
index 53ddb63..808b34f 100644
--- a/remoting/host/encoder.h
+++ b/remoting/host/encoder.h
@@ -6,7 +6,8 @@
#define REMOTING_HOST_ENCODER_H_
#include "base/basictypes.h"
-#include "base/task.h"
+#include "base/callback.h"
+#include "media/base/data_buffer.h"
#include "remoting/base/protocol/chromotocol.pb.h"
#include "remoting/host/capturer.h"
@@ -23,6 +24,24 @@ namespace remoting {
// This class operates asynchronously to enable maximum throughput.
class Encoder {
public:
+
+ // EncodingState is a bitfield that tracks the state of the encoding.
+ // An encoding that consists of a single block could concievably be starting
+ // inprogress and ended at the same time.
+ enum {
+ EncodingStarting = 1 << 0,
+ EncodingInProgress = 1 << 1,
+ EncodingEnded = 1 << 2
+ };
+ 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;
+
virtual ~Encoder() {}
// Encode an image stored in |input_data|. |dirty_rects| contains
@@ -41,13 +60,10 @@ class Encoder {
// Implementation has to ensure that when |data_available_task| is called
// output parameters are stable.
virtual void Encode(const DirtyRects& dirty_rects,
- const uint8** input_data,
+ const uint8* const* input_data,
const int* strides,
bool key_frame,
- UpdateStreamPacketHeader* header,
- scoped_refptr<media::DataBuffer>* output_data,
- bool* encode_done,
- Task* data_available_task) = 0;
+ DataAvailableCallback* data_available_callback) = 0;
// Set the dimension of the incoming images. Need to call this before
// calling Encode().
diff --git a/remoting/host/encoder_verbatim.cc b/remoting/host/encoder_verbatim.cc
index 58525f1..f054ae8 100644
--- a/remoting/host/encoder_verbatim.cc
+++ b/remoting/host/encoder_verbatim.cc
@@ -13,22 +13,35 @@ namespace remoting {
using media::DataBuffer;
void EncoderVerbatim::Encode(const DirtyRects& dirty_rects,
- const uint8** input_data,
+ const uint8* const* input_data,
const int* strides,
bool key_frame,
- UpdateStreamPacketHeader* header,
- scoped_refptr<DataBuffer>* output_data,
- bool* encode_done,
- Task* data_available_task) {
+ DataAvailableCallback* data_available_callback) {
int num_rects = dirty_rects.size();
for (int i = 0; i < num_rects; i++) {
- if (EncodeRect(dirty_rects[i], input_data, strides, header, output_data)) {
- *encode_done = (i == num_rects - 1); // Set for last rect.
- data_available_task->Run();
+ scoped_refptr<DataBuffer> data;
+ gfx::Rect dirty_rect = dirty_rects[i];
+ PixelFormat pixel_format;
+ UpdateStreamEncoding encoding;
+ scoped_ptr<UpdateStreamPacketHeader> header(new UpdateStreamPacketHeader);
+ if (EncodeRect(dirty_rect,
+ input_data,
+ strides,
+ header.get(),
+ &data)) {
+ EncodingState state = EncodingInProgress;
+ if (i == 0) {
+ state |= EncodingStarting;
+ } else if (i == num_rects - 1) {
+ state |= EncodingEnded;
+ }
+ data_available_callback->Run(header.release(),
+ data,
+ state);
}
}
- delete data_available_task;
+ delete data_available_callback;
}
void EncoderVerbatim::SetSize(int width, int height) {
@@ -54,9 +67,9 @@ void EncoderVerbatim::SetPixelFormat(PixelFormat pixel_format) {
}
bool EncoderVerbatim::EncodeRect(const gfx::Rect& dirty,
- const uint8** input_data,
+ const uint8* const* input_data,
const int* strides,
- UpdateStreamPacketHeader* header,
+ UpdateStreamPacketHeader *header,
scoped_refptr<DataBuffer>* output_data) {
const int kPlanes = 3;
@@ -74,10 +87,9 @@ bool EncoderVerbatim::EncodeRect(const gfx::Rect& dirty,
header->set_encoding(EncodingNone);
header->set_pixel_format(pixel_format_);
- *output_data = new DataBuffer(output_size);
- (*output_data)->SetDataSize(output_size);
-
+ *output_data = new DataBuffer(new uint8[output_size], output_size);
uint8* out = (*output_data)->GetWritableData();
+
for (int i = 0; i < kPlanes; ++i) {
const uint8* in = input_data[i];
// Skip over planes that don't have data.
diff --git a/remoting/host/encoder_verbatim.h b/remoting/host/encoder_verbatim.h
index d7a1760..6d371ea 100644
--- a/remoting/host/encoder_verbatim.h
+++ b/remoting/host/encoder_verbatim.h
@@ -18,13 +18,10 @@ class EncoderVerbatim : public Encoder {
virtual ~EncoderVerbatim() {}
virtual void Encode(const DirtyRects& dirty_rects,
- const uint8** input_data,
+ const uint8* const* input_data,
const int* strides,
bool key_frame,
- UpdateStreamPacketHeader* header,
- scoped_refptr<media::DataBuffer>* output_data,
- bool* encode_done,
- Task* data_available_task);
+ DataAvailableCallback* data_available_callback);
virtual void SetSize(int width, int height);
virtual void SetPixelFormat(PixelFormat pixel_format);
@@ -32,10 +29,10 @@ class EncoderVerbatim : public Encoder {
// Encode a single dirty rect. Called by Encode().
// Returns false if there is an error.
bool EncodeRect(const gfx::Rect& dirty,
- const uint8** input_data,
+ const uint8* const* input_data,
const int* strides,
- UpdateStreamPacketHeader* header,
- scoped_refptr<media::DataBuffer>* output_data);
+ UpdateStreamPacketHeader *header,
+ scoped_refptr<media::DataBuffer> *output_data);
int width_;
int height_;
diff --git a/remoting/host/mock_objects.h b/remoting/host/mock_objects.h
index d492376..597c25e 100644
--- a/remoting/host/mock_objects.h
+++ b/remoting/host/mock_objects.h
@@ -37,15 +37,12 @@ class MockEncoder : public Encoder {
public:
MockEncoder() {}
- MOCK_METHOD8(Encode, void(
- const DirtyRects& dirty_rects,
- const uint8** planes,
- const int* strides,
- bool key_frame,
- UpdateStreamPacketHeader* output_data_header,
- scoped_refptr<media::DataBuffer>* output_data,
- bool* encode_done,
- Task* data_available_task));
+ MOCK_METHOD5(Encode, void(
+ const DirtyRects& dirty_rects,
+ const uint8* const* input_data,
+ const int* strides,
+ bool key_frame,
+ DataAvailableCallback* data_available_callback));
MOCK_METHOD2(SetSize, void(int width, int height));
MOCK_METHOD1(SetPixelFormat, void(PixelFormat pixel_format));
@@ -70,7 +67,7 @@ class MockClientConnection : public ClientConnection {
MOCK_METHOD2(SendInitClientMessage, void(int width, int height));
MOCK_METHOD0(SendBeginUpdateStreamMessage, void());
MOCK_METHOD2(SendUpdateStreamPacketMessage,
- void(UpdateStreamPacketHeader* header,
+ void(const UpdateStreamPacketHeader* header,
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 0160993..c434742 100644
--- a/remoting/host/session_manager.cc
+++ b/remoting/host/session_manager.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/logging.h"
+#include "base/scoped_ptr.h"
#include "base/stl_util-inl.h"
#include "media/base/data_buffer.h"
#include "remoting/base/protocol_decoder.h"
@@ -46,12 +47,7 @@ SessionManager::SessionManager(
max_rate_(kDefaultCaptureRate),
started_(false),
recordings_(0),
- rate_control_started_(false),
- capture_width_(0),
- capture_height_(0),
- capture_pixel_format_(PixelFormatInvalid),
- encode_stream_started_(false),
- encode_done_(false) {
+ rate_control_started_(false) {
DCHECK(capture_loop_);
DCHECK(encode_loop_);
DCHECK(network_loop_);
@@ -188,47 +184,45 @@ void SessionManager::DoFinishEncode() {
DoCapture();
}
-void SessionManager::DoEncode() {
- DCHECK_EQ(encode_loop_, MessageLoop::current());
+void SessionManager::DoEncode(const CaptureData *capture_data) {
+ // Take ownership of capture_data.
+ scoped_ptr<const CaptureData> capture_data_owner(capture_data);
- // Reset states about the encode stream.
- encode_done_ = false;
- encode_stream_started_ = false;
+ DCHECK_EQ(encode_loop_, MessageLoop::current());
- DCHECK(!encoded_data_.get());
DCHECK(encoder_.get());
// TODO(hclam): Enable |force_refresh| if a new client was
// added.
- encoder_->SetSize(capture_width_, capture_height_);
- encoder_->SetPixelFormat(capture_pixel_format_);
+ encoder_->SetSize(capture_data->width_, capture_data->height_);
+ encoder_->SetPixelFormat(capture_data->pixel_format_);
encoder_->Encode(
- capture_dirty_rects_,
- capture_data_,
- capture_data_strides_,
+ capture_data->dirty_rects_,
+ capture_data->data_,
+ capture_data->data_strides_,
false,
- &encoded_data_header_,
- &encoded_data_,
- &encode_done_,
- NewRunnableMethod(this, &SessionManager::EncodeDataAvailableTask));
+ NewCallback(this, &SessionManager::EncodeDataAvailableTask));
}
-void SessionManager::DoSendUpdate(
- UpdateStreamPacketHeader* header,
- scoped_refptr<media::DataBuffer> encoded_data,
- bool begin_update, bool end_update) {
+void SessionManager::DoSendUpdate(const UpdateStreamPacketHeader* header,
+ const scoped_refptr<media::DataBuffer> data,
+ Encoder::EncodingState state) {
+ // Take ownership of header.
+ scoped_ptr<const UpdateStreamPacketHeader> header_owner(header);
DCHECK_EQ(network_loop_, MessageLoop::current());
for (size_t i = 0; i < clients_.size(); ++i) {
- if (begin_update)
+ if (state & Encoder::EncodingStarting) {
clients_[i]->SendBeginUpdateStreamMessage();
+ }
- // This will pass the ownership of the DataBuffer to the ClientConnection.
- clients_[i]->SendUpdateStreamPacketMessage(header, encoded_data);
+ clients_[i]->SendUpdateStreamPacketMessage(header, data);
- if (end_update)
+ if (state & Encoder::EncodingEnded) {
clients_[i]->SendEndUpdateStreamMessage();
+ }
}
+ delete header;
}
void SessionManager::DoSendInit(scoped_refptr<ClientConnection> client,
@@ -358,20 +352,25 @@ void SessionManager::ScheduleNextRateControl() {
void SessionManager::CaptureDoneTask() {
DCHECK_EQ(capture_loop_, MessageLoop::current());
+ scoped_ptr<CaptureData> data(new CaptureData);
+
// Save results of the capture.
- capturer_->GetData(capture_data_);
- capturer_->GetDataStride(capture_data_strides_);
- capture_dirty_rects_.clear();
- capturer_->GetDirtyRects(&capture_dirty_rects_);
- capture_pixel_format_ = capturer_->GetPixelFormat();
- capture_width_ = capturer_->GetWidth();
- capture_height_ = capturer_->GetHeight();
+ capturer_->GetData(data->data_);
+ capturer_->GetDataStride(data->data_strides_);
+ capturer_->GetDirtyRects(&data->dirty_rects_);
+ data->pixel_format_ = capturer_->GetPixelFormat();
+ data->width_ = capturer_->GetWidth();
+ data->height_ = capturer_->GetHeight();
encode_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &SessionManager::DoEncode));
+ FROM_HERE,
+ NewRunnableMethod(this, &SessionManager::DoEncode, data.release()));
}
-void SessionManager::EncodeDataAvailableTask() {
+void SessionManager::EncodeDataAvailableTask(
+ const UpdateStreamPacketHeader *header,
+ const scoped_refptr<media::DataBuffer>& data,
+ Encoder::EncodingState state) {
DCHECK_EQ(encode_loop_, MessageLoop::current());
// Before a new encode task starts, notify clients a new update
@@ -382,20 +381,11 @@ void SessionManager::EncodeDataAvailableTask() {
FROM_HERE,
NewRunnableMethod(this,
&SessionManager::DoSendUpdate,
- &encoded_data_header_,
- encoded_data_,
- !encode_stream_started_,
- encode_done_));
-
- // Since we have received data from the Encoder, mark the encode
- // stream has started.
- encode_stream_started_ = true;
-
- // Give up the ownership of DataBuffer since it is passed to
- // the ClientConnections.
- encoded_data_ = NULL;
+ header,
+ data,
+ state));
- if (encode_done_) {
+ if (state == Encoder::EncodingEnded) {
capture_loop_->PostTask(
FROM_HERE, NewRunnableMethod(this, &SessionManager::DoFinishEncode));
}
diff --git a/remoting/host/session_manager.h b/remoting/host/session_manager.h
index 677e3bd..54aae70 100644
--- a/remoting/host/session_manager.h
+++ b/remoting/host/session_manager.h
@@ -14,6 +14,7 @@
#include "base/time.h"
#include "remoting/base/protocol/chromotocol.pb.h"
#include "remoting/host/capturer.h"
+#include "remoting/host/encoder.h"
namespace media {
@@ -95,6 +96,18 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
void RemoveClient(scoped_refptr<ClientConnection> client);
private:
+
+ // Stores the data and information of a capture to pass off to the
+ // encoding thread.
+ struct CaptureData {
+ DirtyRects dirty_rects_;
+ const uint8* data_[3];
+ int data_strides_[3];
+ int width_;
+ int height_;
+ PixelFormat pixel_format_;
+ };
+
void DoStart();
void DoPause();
void DoStartRateControl();
@@ -102,12 +115,14 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
void DoCapture();
void DoFinishEncode();
- void DoEncode();
- void DoSendUpdate(
- UpdateStreamPacketHeader* header,
- scoped_refptr<media::DataBuffer> encoded_data,
- bool begin_update,
- bool end_update);
+
+ // DoEncode takes ownership of capture_data and is responsible for deleting
+ // it.
+ void DoEncode(const CaptureData *capture_data);
+ // DoSendUpdate takes ownership of header and is responsible for deleting it.
+ void DoSendUpdate(const UpdateStreamPacketHeader* header,
+ const scoped_refptr<media::DataBuffer> data,
+ Encoder::EncodingState state);
void DoSendInit(scoped_refptr<ClientConnection> client,
int width, int height);
void DoGetInitInfo(scoped_refptr<ClientConnection> client);
@@ -124,7 +139,11 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
void ScheduleNextRateControl();
void CaptureDoneTask();
- void EncodeDataAvailableTask();
+ // EncodeDataAvailableTask takes ownership of header and is responsible for
+ // deleting it.
+ void EncodeDataAvailableTask(const UpdateStreamPacketHeader *header,
+ const scoped_refptr<media::DataBuffer>& data,
+ Encoder::EncodingState state);
// Message loops used by this class.
MessageLoop* capture_loop_;
@@ -160,28 +179,6 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
// The following member is accessed on the network thread.
bool rate_control_started_;
- // Stores the data and information of the last capture done.
- // These members are written on capture thread and read on encode thread.
- // It is guranteed the read happens after the write.
- DirtyRects capture_dirty_rects_;
- const uint8* capture_data_[3];
- int capture_data_strides_[3];
- int capture_width_;
- int capture_height_;
- PixelFormat capture_pixel_format_;
-
- // The following members are accessed on the encode thread.
- // Output parameter written by Encoder to carry encoded data.
- UpdateStreamPacketHeader encoded_data_header_;
- scoped_refptr<media::DataBuffer> encoded_data_;
-
- // True if we have started receiving encoded data from the Encoder.
- bool encode_stream_started_;
-
- // Output parameter written by Encoder to notify the end of encoded data
- // stream.
- bool encode_done_;
-
DISALLOW_COPY_AND_ASSIGN(SessionManager);
};
diff --git a/remoting/host/session_manager_unittest.cc b/remoting/host/session_manager_unittest.cc
index 008d063..a4134a8 100644
--- a/remoting/host/session_manager_unittest.cc
+++ b/remoting/host/session_manager_unittest.cc
@@ -28,8 +28,8 @@ static uint8* kData[3] = {
reinterpret_cast<uint8*>(0x02),
reinterpret_cast<uint8*>(0x03),
};
-static const PixelFormat kFormat =
- PixelFormatRgb32;
+static const PixelFormat kFormat = PixelFormatRgb32;
+static const UpdateStreamEncoding kEncoding = EncodingNone;
class SessionManagerTest : public testing::Test {
public:
@@ -67,12 +67,18 @@ ACTION(RunSimpleTask) {
delete arg0;
}
-ACTION_P2(FinishDecode, header, data) {
- *arg4 = header;
- *arg5 = data;
- *arg6 = true;
- arg7->Run();
- delete arg7;
+ACTION_P3(FinishDecode, rects, buffer, header) {
+ gfx::Rect& rect = (*rects)[0];
+ 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);
+ arg4->Run(header, *buffer, state);
}
ACTION_P(AssignCaptureData, data) {
@@ -81,6 +87,10 @@ ACTION_P(AssignCaptureData, data) {
arg0[2] = data[2];
}
+ACTION_P(AssignDirtyRect, rects) {
+ *arg0 = *rects;
+}
+
TEST_F(SessionManagerTest, OneRecordCycle) {
Init();
@@ -96,8 +106,12 @@ TEST_F(SessionManagerTest, OneRecordCycle) {
// First the capturer is called.
EXPECT_CALL(*capturer_, CaptureDirtyRects(NotNull()))
.WillOnce(RunSimpleTask());
- // TODO(hclam): Return DirtyRects for verification.
- EXPECT_CALL(*capturer_, GetDirtyRects(NotNull()));
+
+ // Create a dirty rect that can be verified.
+ DirtyRects rects;
+ rects.push_back(gfx::Rect(0, 0, 10, 10));
+ EXPECT_CALL(*capturer_, GetDirtyRects(NotNull()))
+ .WillOnce(AssignDirtyRect(&rects));
EXPECT_CALL(*capturer_, GetData(NotNull()))
.WillOnce(AssignCaptureData(kData));
EXPECT_CALL(*capturer_, GetDataStride(NotNull()))
@@ -106,19 +120,17 @@ TEST_F(SessionManagerTest, OneRecordCycle) {
.WillOnce(Return(kFormat));
// Expect the encoder be called.
- UpdateStreamPacketHeader header;
scoped_refptr<media::DataBuffer> buffer = new media::DataBuffer(0);
EXPECT_CALL(*encoder_, SetSize(kWidth, kHeight));
EXPECT_CALL(*encoder_, SetPixelFormat(kFormat));
- // TODO(hclam): Expect the content of the dirty rects.
- EXPECT_CALL(*encoder_,
- Encode(_, NotNull(), NotNull(), false, NotNull(),
- NotNull(), NotNull(), NotNull()))
- .WillOnce(FinishDecode(header, buffer));
+ UpdateStreamPacketHeader *header = new UpdateStreamPacketHeader;
+ EXPECT_CALL(*encoder_, Encode(rects, NotNull(), NotNull(), false, NotNull()))
+ .WillOnce(FinishDecode(&rects, &buffer, header));
// Expect the client be notified.
EXPECT_CALL(*client_, SendBeginUpdateStreamMessage());
- EXPECT_CALL(*client_, SendUpdateStreamPacketMessage(NotNull(), buffer));
+
+ EXPECT_CALL(*client_, SendUpdateStreamPacketMessage(header ,buffer));
EXPECT_CALL(*client_, SendEndUpdateStreamMessage());
EXPECT_CALL(*client_, GetPendingUpdateStreamMessages())
.Times(AtLeast(0))