blob: 2736c3ecb1a3a6115ddb906e2016fe29c87e1499 [file] [log] [blame]
[email protected]fb13c762010-07-24 02:22:071// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <deque>
6#include <stdlib.h>
7
8#include "gfx/rect.h"
9#include "media/base/video_frame.h"
10#include "remoting/base/codec_test.h"
[email protected]8ea7a1672010-10-04 19:48:4211#include "remoting/base/decoder.h"
[email protected]fb13c762010-07-24 02:22:0712#include "remoting/base/encoder.h"
13#include "remoting/base/mock_objects.h"
[email protected]66db1af92010-07-27 01:42:4614#include "remoting/base/protocol_util.h"
[email protected]fb13c762010-07-24 02:22:0715#include "testing/gtest/include/gtest/gtest.h"
16
17static const int kWidth = 320;
18static const int kHeight = 240;
19static const int kBytesPerPixel = 4;
20
21// Some sample rects for testing.
22static const gfx::Rect kTestRects[] = {
23 gfx::Rect(0, 0, kWidth, kHeight),
24 gfx::Rect(0, 0, kWidth / 2, kHeight / 2),
25 gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
26 gfx::Rect(16, 16, 16, 16),
[email protected]66db1af92010-07-27 01:42:4627 gfx::Rect(128, 64, 32, 32),
[email protected]fb13c762010-07-24 02:22:0728};
29
30namespace remoting {
31
32// A class to test that the state transition of the Encoder is correct.
33class EncoderStateTester {
34 public:
35 EncoderStateTester()
36 : next_state_(Encoder::EncodingStarting) {
37 }
38
39 ~EncoderStateTester() {
40 EXPECT_EQ(Encoder::EncodingStarting, next_state_);
41 }
42
43 // Set the state output of the Encoder.
44 void ReceivedState(Encoder::EncodingState state) {
45 if (state & Encoder::EncodingStarting) {
46 EXPECT_EQ(Encoder::EncodingStarting, next_state_);
47 next_state_ = Encoder::EncodingInProgress | Encoder::EncodingEnded;
48 } else {
49 EXPECT_FALSE(next_state_ & Encoder::EncodingStarting);
50 }
51
52 if (state & Encoder::EncodingInProgress) {
53 EXPECT_TRUE(next_state_ & Encoder::EncodingInProgress);
54 }
55
56 if (state & Encoder::EncodingEnded) {
57 EXPECT_TRUE(next_state_ & Encoder::EncodingEnded);
58 next_state_ = Encoder::EncodingStarting;
59 }
60 }
61
62 private:
63 Encoder::EncodingState next_state_;
64
65 DISALLOW_COPY_AND_ASSIGN(EncoderStateTester);
66};
67
68// A class to test the message output of the encoder.
69class EncoderMessageTester {
70 public:
71 EncoderMessageTester()
72 : begin_rect_(0),
73 rect_data_(0),
74 end_rect_(0),
[email protected]66db1af92010-07-27 01:42:4675 added_rects_(0),
[email protected]fb13c762010-07-24 02:22:0776 state_(kWaitingForBeginRect),
77 strict_(false) {
78 }
79
80 ~EncoderMessageTester() {
81 EXPECT_EQ(begin_rect_, end_rect_);
[email protected]df10bf12010-09-28 22:19:4882 EXPECT_GT(begin_rect_, 0);
[email protected]fb13c762010-07-24 02:22:0783 EXPECT_EQ(kWaitingForBeginRect, state_);
[email protected]df10bf12010-09-28 22:19:4884 if (strict_) {
85 EXPECT_EQ(added_rects_, begin_rect_);
[email protected]66db1af92010-07-27 01:42:4686 }
[email protected]fb13c762010-07-24 02:22:0787 }
88
89 // Test that we received the correct message.
[email protected]53a45972010-08-24 23:05:0590 void ReceivedMessage(ChromotingHostMessage* message) {
[email protected]fb13c762010-07-24 02:22:0791 EXPECT_TRUE(message->has_update_stream_packet());
92
93 if (state_ == kWaitingForBeginRect) {
94 EXPECT_TRUE(message->update_stream_packet().has_begin_rect());
95 state_ = kWaitingForRectData;
96 ++begin_rect_;
97
98 if (strict_) {
99 gfx::Rect rect = rects_.front();
100 rects_.pop_front();
101 EXPECT_EQ(rect.x(), message->update_stream_packet().begin_rect().x());
102 EXPECT_EQ(rect.y(), message->update_stream_packet().begin_rect().y());
103 EXPECT_EQ(rect.width(),
104 message->update_stream_packet().begin_rect().width());
105 EXPECT_EQ(rect.height(),
106 message->update_stream_packet().begin_rect().height());
107 }
108 } else {
109 EXPECT_FALSE(message->update_stream_packet().has_begin_rect());
110 }
111
112 if (state_ == kWaitingForRectData) {
113 if (message->update_stream_packet().has_rect_data()) {
114 ++rect_data_;
115 }
116
117 if (message->update_stream_packet().has_end_rect()) {
118 // Expect that we have received some data.
119 EXPECT_GT(rect_data_, 0);
120 rect_data_ = 0;
121 state_ = kWaitingForBeginRect;
122 ++end_rect_;
123 }
124 }
125 }
126
127 void set_strict(bool strict) {
128 strict_ = strict;
129 }
130
131 void AddRects(const gfx::Rect* rects, int count) {
132 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
[email protected]66db1af92010-07-27 01:42:46133 added_rects_ += count;
[email protected]fb13c762010-07-24 02:22:07134 }
135
136 private:
137 enum State {
138 kWaitingForBeginRect,
139 kWaitingForRectData,
140 };
141
142 int begin_rect_;
143 int rect_data_;
144 int end_rect_;
[email protected]66db1af92010-07-27 01:42:46145 int added_rects_;
[email protected]fb13c762010-07-24 02:22:07146 State state_;
147 bool strict_;
148
149 std::deque<gfx::Rect> rects_;
150
151 DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester);
152};
153
154class DecoderTester {
155 public:
156 DecoderTester(Decoder* decoder)
157 : strict_(false),
158 decoder_(decoder),
159 decode_done_(false) {
160 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32,
161 kWidth, kHeight,
162 base::TimeDelta(),
163 base::TimeDelta(), &frame_);
164 EXPECT_TRUE(frame_.get());
165 }
166
[email protected]53a45972010-08-24 23:05:05167 void ReceivedMessage(ChromotingHostMessage* message) {
[email protected]fb13c762010-07-24 02:22:07168 if (message->has_update_stream_packet()) {
[email protected]622b7882010-09-29 17:34:32169 EXPECT_TRUE(decoder_->PartialDecode(message));
[email protected]fb13c762010-07-24 02:22:07170 return;
171 }
172
173 if (message->has_begin_update_stream()) {
[email protected]622b7882010-09-29 17:34:32174 EXPECT_TRUE(decoder_->BeginDecode(
[email protected]fb13c762010-07-24 02:22:07175 frame_, &update_rects_,
176 NewRunnableMethod(this, &DecoderTester::OnPartialDecodeDone),
[email protected]622b7882010-09-29 17:34:32177 NewRunnableMethod(this, &DecoderTester::OnDecodeDone)));
[email protected]fb13c762010-07-24 02:22:07178 }
179
180 if (message->has_end_update_stream()) {
181 decoder_->EndDecode();
182 }
183 delete message;
[email protected]fb13c762010-07-24 02:22:07184 }
185
186 void set_strict(bool strict) {
187 strict_ = strict;
188 }
189
190 void set_capture_data(scoped_refptr<CaptureData> data) {
191 capture_data_ = data;
192 }
193
194 void AddRects(const gfx::Rect* rects, int count) {
195 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
196 }
197
198 bool decode_done() const { return decode_done_; }
199 void reset_decode_done() { decode_done_ = false; }
200
201 private:
202 void OnPartialDecodeDone() {
203 if (!strict_)
204 return;
[email protected]66db1af92010-07-27 01:42:46205
206 // Test the content of the update rect.
[email protected]fb13c762010-07-24 02:22:07207 for (size_t i = 0; i < update_rects_.size(); ++i) {
208 EXPECT_FALSE(rects_.empty());
209 gfx::Rect rect = rects_.front();
210 rects_.pop_front();
211 EXPECT_EQ(rect, update_rects_[i]);
[email protected]66db1af92010-07-27 01:42:46212
213 EXPECT_EQ(frame_->stride(0), capture_data_->data_planes().strides[0]);
214 const int stride = frame_->stride(0);
215 const int offset = stride * update_rects_[i].y() +
216 kBytesPerPixel * update_rects_[i].x();
217 const uint8* original = capture_data_->data_planes().data[0] + offset;
218 const uint8* decoded = frame_->data(0) + offset;
219 const int row_size = kBytesPerPixel * update_rects_[i].width();
220 for (int y = 0; y < update_rects_[i].height(); ++y) {
221 EXPECT_EQ(0, memcmp(original, decoded, row_size))
222 << "Row " << y << " is different";
223 original += stride;
224 decoded += stride;
225 }
[email protected]fb13c762010-07-24 02:22:07226 }
227 }
228
229 void OnDecodeDone() {
230 decode_done_ = true;
231 if (!strict_)
232 return;
233
234 EXPECT_TRUE(capture_data_.get());
235 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) {
236 if (!frame_->data(i) || !capture_data_->data_planes().data[i])
237 continue;
238 // TODO(hclam): HAndle YUV.
239 int size = capture_data_->data_planes().strides[i] * kHeight;
240 EXPECT_EQ(0, memcmp(capture_data_->data_planes().data[i],
241 frame_->data(i), size));
242 }
243 }
244
245 bool strict_;
246 std::deque<gfx::Rect> rects_;
247 UpdatedRects update_rects_;
248 Decoder* decoder_;
249 scoped_refptr<media::VideoFrame> frame_;
250 scoped_refptr<CaptureData> capture_data_;
251 bool decode_done_;
252
253 DISALLOW_COPY_AND_ASSIGN(DecoderTester);
254};
255
[email protected]8ea7a1672010-10-04 19:48:42256// The EncoderTester provides a hook for retrieving the data, and passing the
257// message to other subprograms for validaton.
[email protected]fb13c762010-07-24 02:22:07258class EncoderTester {
259 public:
260 EncoderTester(EncoderMessageTester* message_tester,
261 EncoderStateTester* state_tester)
262 : message_tester_(message_tester),
263 state_tester_(state_tester),
264 decoder_tester_(NULL),
265 data_available_(0) {
266 }
267
268 ~EncoderTester() {
269 EXPECT_GT(data_available_, 0);
270 }
271
[email protected]53a45972010-08-24 23:05:05272 void DataAvailable(ChromotingHostMessage* message,
[email protected]fb13c762010-07-24 02:22:07273 Encoder::EncodingState state) {
274 ++data_available_;
275 message_tester_->ReceivedMessage(message);
276 state_tester_->ReceivedState(state);
277
278 // Send the message to the DecoderTester.
279 if (decoder_tester_) {
280 if (state & Encoder::EncodingStarting) {
[email protected]53a45972010-08-24 23:05:05281 ChromotingHostMessage* begin_update = new ChromotingHostMessage();
[email protected]fb13c762010-07-24 02:22:07282 begin_update->mutable_begin_update_stream();
283 decoder_tester_->ReceivedMessage(begin_update);
284 }
285
286 if (state & Encoder::EncodingInProgress) {
287 decoder_tester_->ReceivedMessage(message);
288 }
289
290 if (state & Encoder::EncodingEnded) {
[email protected]53a45972010-08-24 23:05:05291 ChromotingHostMessage* end_update = new ChromotingHostMessage();
[email protected]fb13c762010-07-24 02:22:07292 end_update->mutable_end_update_stream();
293 decoder_tester_->ReceivedMessage(end_update);
294 }
[email protected]3ea428d2010-07-24 11:23:23295 } else {
[email protected]fb13c762010-07-24 02:22:07296 delete message;
[email protected]3ea428d2010-07-24 11:23:23297 }
[email protected]fb13c762010-07-24 02:22:07298 }
299
300 void AddRects(const gfx::Rect* rects, int count) {
301 message_tester_->AddRects(rects, count);
302 }
303
304 void set_decoder_tester(DecoderTester* decoder_tester) {
305 decoder_tester_ = decoder_tester;
306 }
307
308 private:
309 EncoderMessageTester* message_tester_;
310 EncoderStateTester* state_tester_;
311 DecoderTester* decoder_tester_;
312 int data_available_;
313
314 DISALLOW_COPY_AND_ASSIGN(EncoderTester);
315};
316
317scoped_refptr<CaptureData> PrepareEncodeData(PixelFormat format,
318 uint8** memory) {
319 // TODO(hclam): Support also YUV format.
320 CHECK(format == PixelFormatRgb32);
321 int size = kWidth * kHeight * kBytesPerPixel;
322
323 *memory = new uint8[size];
324 srand(0);
325 for (int i = 0; i < size; ++i) {
326 (*memory)[i] = rand() % 256;
327 }
328
329 DataPlanes planes;
330 memset(planes.data, 0, sizeof(planes.data));
331 memset(planes.strides, 0, sizeof(planes.strides));
332 planes.data[0] = *memory;
333 planes.strides[0] = kWidth * kBytesPerPixel;
334
335 scoped_refptr<CaptureData> data =
336 new CaptureData(planes, kWidth, kHeight, format);
337 return data;
338}
339
340static void TestEncodingRects(Encoder* encoder,
341 EncoderTester* tester,
342 scoped_refptr<CaptureData> data,
343 const gfx::Rect* rects, int count) {
344 data->mutable_dirty_rects().clear();
[email protected]88552a92010-08-06 22:50:00345 for (int i = 0; i < count; ++i) {
346 data->mutable_dirty_rects().insert(rects[i]);
347 }
[email protected]fb13c762010-07-24 02:22:07348 tester->AddRects(rects, count);
349
350 encoder->Encode(data, true,
351 NewCallback(tester, &EncoderTester::DataAvailable));
352}
353
354void TestEncoder(Encoder* encoder, bool strict) {
355 EncoderMessageTester message_tester;
356 message_tester.set_strict(strict);
357
358 EncoderStateTester state_tester;
359 EncoderTester tester(&message_tester, &state_tester);
360
361 uint8* memory;
362 scoped_refptr<CaptureData> data =
363 PrepareEncodeData(PixelFormatRgb32, &memory);
364
365 TestEncodingRects(encoder, &tester, data, kTestRects, 1);
366 TestEncodingRects(encoder, &tester, data, kTestRects + 1, 1);
367 TestEncodingRects(encoder, &tester, data, kTestRects + 2, 1);
368 TestEncodingRects(encoder, &tester, data, kTestRects + 3, 2);
[email protected]3ea428d2010-07-24 11:23:23369 delete [] memory;
[email protected]fb13c762010-07-24 02:22:07370}
371
372static void TestEncodingRects(Encoder* encoder,
373 EncoderTester* encoder_tester,
374 DecoderTester* decoder_tester,
375 scoped_refptr<CaptureData> data,
376 const gfx::Rect* rects, int count) {
377 data->mutable_dirty_rects().clear();
[email protected]88552a92010-08-06 22:50:00378 for (int i = 0; i < count; ++i) {
379 data->mutable_dirty_rects().insert(rects[i]);
380 }
[email protected]fb13c762010-07-24 02:22:07381 encoder_tester->AddRects(rects, count);
382 decoder_tester->AddRects(rects, count);
383 decoder_tester->reset_decode_done();
384
[email protected]66db1af92010-07-27 01:42:46385 // Generate random data for the updated rects.
386 srand(0);
387 for (int i = 0; i < count; ++i) {
388 const gfx::Rect rect = rects[i];
389 const int bytes_per_pixel = GetBytesPerPixel(data->pixel_format());
390 const int row_size = bytes_per_pixel * rect.width();
391 uint8* memory = data->data_planes().data[0] +
392 data->data_planes().strides[0] * rect.y() +
393 bytes_per_pixel * rect.x();
394 for (int y = 0; y < rect.height(); ++y) {
395 for (int x = 0; x < row_size; ++x)
396 memory[x] = rand() % 256;
397 memory += data->data_planes().strides[0];
398 }
399 }
400
[email protected]fb13c762010-07-24 02:22:07401 encoder->Encode(data, true,
402 NewCallback(encoder_tester, &EncoderTester::DataAvailable));
403 EXPECT_TRUE(decoder_tester->decode_done());
404}
405
406void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) {
407 EncoderMessageTester message_tester;
408 message_tester.set_strict(strict);
409
410 EncoderStateTester state_tester;
411 EncoderTester encoder_tester(&message_tester, &state_tester);
412
413 uint8* memory;
414 scoped_refptr<CaptureData> data =
415 PrepareEncodeData(PixelFormatRgb32, &memory);
416 DecoderTester decoder_tester(decoder);
417 decoder_tester.set_strict(strict);
418 decoder_tester.set_capture_data(data);
419 encoder_tester.set_decoder_tester(&decoder_tester);
420
421 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
422 kTestRects, 1);
423 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
424 kTestRects + 1, 1);
425 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
426 kTestRects + 2, 1);
427 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
428 kTestRects + 3, 2);
[email protected]3ea428d2010-07-24 11:23:23429 delete [] memory;
[email protected]fb13c762010-07-24 02:22:07430}
431
432} // namespace remoting
433
434DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::DecoderTester);