OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <deque> | 5 #include <deque> |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "gfx/rect.h" | 8 #include "gfx/rect.h" |
9 #include "media/base/video_frame.h" | 9 #include "media/base/video_frame.h" |
10 #include "remoting/base/codec_test.h" | 10 #include "remoting/base/codec_test.h" |
11 #include "remoting/base/encoder.h" | 11 #include "remoting/base/encoder.h" |
12 #include "remoting/base/mock_objects.h" | 12 #include "remoting/base/mock_objects.h" |
| 13 #include "remoting/base/protocol_util.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
14 | 15 |
15 static const int kWidth = 320; | 16 static const int kWidth = 320; |
16 static const int kHeight = 240; | 17 static const int kHeight = 240; |
17 static const int kBytesPerPixel = 4; | 18 static const int kBytesPerPixel = 4; |
18 | 19 |
19 // Some sample rects for testing. | 20 // Some sample rects for testing. |
20 static const gfx::Rect kTestRects[] = { | 21 static const gfx::Rect kTestRects[] = { |
21 gfx::Rect(0, 0, kWidth, kHeight), | 22 gfx::Rect(0, 0, kWidth, kHeight), |
22 gfx::Rect(0, 0, kWidth / 2, kHeight / 2), | 23 gfx::Rect(0, 0, kWidth / 2, kHeight / 2), |
23 gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2), | 24 gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2), |
24 gfx::Rect(16, 16, 16, 16), | 25 gfx::Rect(16, 16, 16, 16), |
25 gfx::Rect(128, 64, 32, 32) | 26 gfx::Rect(128, 64, 32, 32), |
26 }; | 27 }; |
27 | 28 |
28 namespace remoting { | 29 namespace remoting { |
29 | 30 |
30 // A class to test that the state transition of the Encoder is correct. | 31 // A class to test that the state transition of the Encoder is correct. |
31 class EncoderStateTester { | 32 class EncoderStateTester { |
32 public: | 33 public: |
33 EncoderStateTester() | 34 EncoderStateTester() |
34 : next_state_(Encoder::EncodingStarting) { | 35 : next_state_(Encoder::EncodingStarting) { |
35 } | 36 } |
(...skipping 27 matching lines...) Expand all Loading... |
63 DISALLOW_COPY_AND_ASSIGN(EncoderStateTester); | 64 DISALLOW_COPY_AND_ASSIGN(EncoderStateTester); |
64 }; | 65 }; |
65 | 66 |
66 // A class to test the message output of the encoder. | 67 // A class to test the message output of the encoder. |
67 class EncoderMessageTester { | 68 class EncoderMessageTester { |
68 public: | 69 public: |
69 EncoderMessageTester() | 70 EncoderMessageTester() |
70 : begin_rect_(0), | 71 : begin_rect_(0), |
71 rect_data_(0), | 72 rect_data_(0), |
72 end_rect_(0), | 73 end_rect_(0), |
| 74 added_rects_(0), |
73 state_(kWaitingForBeginRect), | 75 state_(kWaitingForBeginRect), |
74 strict_(false) { | 76 strict_(false) { |
75 } | 77 } |
76 | 78 |
77 ~EncoderMessageTester() { | 79 ~EncoderMessageTester() { |
78 EXPECT_EQ(begin_rect_, end_rect_); | 80 EXPECT_EQ(begin_rect_, end_rect_); |
79 EXPECT_EQ(kWaitingForBeginRect, state_); | 81 EXPECT_EQ(kWaitingForBeginRect, state_); |
| 82 if (strict_){ |
| 83 EXPECT_EQ(begin_rect_, added_rects_); |
| 84 } |
80 } | 85 } |
81 | 86 |
82 // Test that we received the correct message. | 87 // Test that we received the correct message. |
83 void ReceivedMessage(HostMessage* message) { | 88 void ReceivedMessage(HostMessage* message) { |
84 EXPECT_TRUE(message->has_update_stream_packet()); | 89 EXPECT_TRUE(message->has_update_stream_packet()); |
85 | 90 |
86 if (state_ == kWaitingForBeginRect) { | 91 if (state_ == kWaitingForBeginRect) { |
87 EXPECT_TRUE(message->update_stream_packet().has_begin_rect()); | 92 EXPECT_TRUE(message->update_stream_packet().has_begin_rect()); |
88 state_ = kWaitingForRectData; | 93 state_ = kWaitingForRectData; |
89 ++begin_rect_; | 94 ++begin_rect_; |
(...skipping 26 matching lines...) Expand all Loading... |
116 } | 121 } |
117 } | 122 } |
118 } | 123 } |
119 | 124 |
120 void set_strict(bool strict) { | 125 void set_strict(bool strict) { |
121 strict_ = strict; | 126 strict_ = strict; |
122 } | 127 } |
123 | 128 |
124 void AddRects(const gfx::Rect* rects, int count) { | 129 void AddRects(const gfx::Rect* rects, int count) { |
125 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); | 130 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); |
| 131 added_rects_ += count; |
126 } | 132 } |
127 | 133 |
128 private: | 134 private: |
129 enum State { | 135 enum State { |
130 kWaitingForBeginRect, | 136 kWaitingForBeginRect, |
131 kWaitingForRectData, | 137 kWaitingForRectData, |
132 }; | 138 }; |
133 | 139 |
134 int begin_rect_; | 140 int begin_rect_; |
135 int rect_data_; | 141 int rect_data_; |
136 int end_rect_; | 142 int end_rect_; |
| 143 int added_rects_; |
137 State state_; | 144 State state_; |
138 bool strict_; | 145 bool strict_; |
139 | 146 |
140 std::deque<gfx::Rect> rects_; | 147 std::deque<gfx::Rect> rects_; |
141 | 148 |
142 DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester); | 149 DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester); |
143 }; | 150 }; |
144 | 151 |
145 class DecoderTester { | 152 class DecoderTester { |
146 public: | 153 public: |
(...skipping 18 matching lines...) Expand all Loading... |
165 decoder_->BeginDecode( | 172 decoder_->BeginDecode( |
166 frame_, &update_rects_, | 173 frame_, &update_rects_, |
167 NewRunnableMethod(this, &DecoderTester::OnPartialDecodeDone), | 174 NewRunnableMethod(this, &DecoderTester::OnPartialDecodeDone), |
168 NewRunnableMethod(this, &DecoderTester::OnDecodeDone)); | 175 NewRunnableMethod(this, &DecoderTester::OnDecodeDone)); |
169 } | 176 } |
170 | 177 |
171 if (message->has_end_update_stream()) { | 178 if (message->has_end_update_stream()) { |
172 decoder_->EndDecode(); | 179 decoder_->EndDecode(); |
173 } | 180 } |
174 delete message; | 181 delete message; |
175 return; | |
176 } | 182 } |
177 | 183 |
178 void set_strict(bool strict) { | 184 void set_strict(bool strict) { |
179 strict_ = strict; | 185 strict_ = strict; |
180 } | 186 } |
181 | 187 |
182 void set_capture_data(scoped_refptr<CaptureData> data) { | 188 void set_capture_data(scoped_refptr<CaptureData> data) { |
183 capture_data_ = data; | 189 capture_data_ = data; |
184 } | 190 } |
185 | 191 |
186 void AddRects(const gfx::Rect* rects, int count) { | 192 void AddRects(const gfx::Rect* rects, int count) { |
187 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); | 193 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count); |
188 } | 194 } |
189 | 195 |
190 bool decode_done() const { return decode_done_; } | 196 bool decode_done() const { return decode_done_; } |
191 void reset_decode_done() { decode_done_ = false; } | 197 void reset_decode_done() { decode_done_ = false; } |
192 | 198 |
193 private: | 199 private: |
194 void OnPartialDecodeDone() { | 200 void OnPartialDecodeDone() { |
195 if (!strict_) | 201 if (!strict_) |
196 return; | 202 return; |
| 203 |
| 204 // Test the content of the update rect. |
197 for (size_t i = 0; i < update_rects_.size(); ++i) { | 205 for (size_t i = 0; i < update_rects_.size(); ++i) { |
| 206 LOG(INFO) << "Testing Rect " << i; |
198 EXPECT_FALSE(rects_.empty()); | 207 EXPECT_FALSE(rects_.empty()); |
199 gfx::Rect rect = rects_.front(); | 208 gfx::Rect rect = rects_.front(); |
200 rects_.pop_front(); | 209 rects_.pop_front(); |
201 EXPECT_EQ(rect, update_rects_[i]); | 210 EXPECT_EQ(rect, update_rects_[i]); |
| 211 |
| 212 EXPECT_EQ(frame_->stride(0), capture_data_->data_planes().strides[0]); |
| 213 const int stride = frame_->stride(0); |
| 214 const int offset = stride * update_rects_[i].y() + |
| 215 kBytesPerPixel * update_rects_[i].x(); |
| 216 const uint8* original = capture_data_->data_planes().data[0] + offset; |
| 217 const uint8* decoded = frame_->data(0) + offset; |
| 218 const int row_size = kBytesPerPixel * update_rects_[i].width(); |
| 219 for (int y = 0; y < update_rects_[i].height(); ++y) { |
| 220 EXPECT_EQ(0, memcmp(original, decoded, row_size)) |
| 221 << "Row " << y << " is different"; |
| 222 original += stride; |
| 223 decoded += stride; |
| 224 } |
202 } | 225 } |
203 } | 226 } |
204 | 227 |
205 void OnDecodeDone() { | 228 void OnDecodeDone() { |
206 decode_done_ = true; | 229 decode_done_ = true; |
207 if (!strict_) | 230 if (!strict_) |
208 return; | 231 return; |
209 | 232 |
210 EXPECT_TRUE(capture_data_.get()); | 233 EXPECT_TRUE(capture_data_.get()); |
211 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { | 234 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 DecoderTester* decoder_tester, | 370 DecoderTester* decoder_tester, |
348 scoped_refptr<CaptureData> data, | 371 scoped_refptr<CaptureData> data, |
349 const gfx::Rect* rects, int count) { | 372 const gfx::Rect* rects, int count) { |
350 data->mutable_dirty_rects().clear(); | 373 data->mutable_dirty_rects().clear(); |
351 data->mutable_dirty_rects().insert( | 374 data->mutable_dirty_rects().insert( |
352 data->mutable_dirty_rects().begin(), rects, rects + count); | 375 data->mutable_dirty_rects().begin(), rects, rects + count); |
353 encoder_tester->AddRects(rects, count); | 376 encoder_tester->AddRects(rects, count); |
354 decoder_tester->AddRects(rects, count); | 377 decoder_tester->AddRects(rects, count); |
355 decoder_tester->reset_decode_done(); | 378 decoder_tester->reset_decode_done(); |
356 | 379 |
| 380 // Generate random data for the updated rects. |
| 381 srand(0); |
| 382 for (int i = 0; i < count; ++i) { |
| 383 const gfx::Rect rect = rects[i]; |
| 384 const int bytes_per_pixel = GetBytesPerPixel(data->pixel_format()); |
| 385 const int row_size = bytes_per_pixel * rect.width(); |
| 386 uint8* memory = data->data_planes().data[0] + |
| 387 data->data_planes().strides[0] * rect.y() + |
| 388 bytes_per_pixel * rect.x(); |
| 389 for (int y = 0; y < rect.height(); ++y) { |
| 390 for (int x = 0; x < row_size; ++x) |
| 391 memory[x] = rand() % 256; |
| 392 memory += data->data_planes().strides[0]; |
| 393 } |
| 394 } |
| 395 |
357 encoder->Encode(data, true, | 396 encoder->Encode(data, true, |
358 NewCallback(encoder_tester, &EncoderTester::DataAvailable)); | 397 NewCallback(encoder_tester, &EncoderTester::DataAvailable)); |
359 EXPECT_TRUE(decoder_tester->decode_done()); | 398 EXPECT_TRUE(decoder_tester->decode_done()); |
360 } | 399 } |
361 | 400 |
362 void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) { | 401 void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) { |
363 EncoderMessageTester message_tester; | 402 EncoderMessageTester message_tester; |
364 message_tester.set_strict(strict); | 403 message_tester.set_strict(strict); |
365 | 404 |
366 EncoderStateTester state_tester; | 405 EncoderStateTester state_tester; |
(...skipping 14 matching lines...) Expand all Loading... |
381 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data, | 420 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data, |
382 kTestRects + 2, 1); | 421 kTestRects + 2, 1); |
383 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data, | 422 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data, |
384 kTestRects + 3, 2); | 423 kTestRects + 3, 2); |
385 delete [] memory; | 424 delete [] memory; |
386 } | 425 } |
387 | 426 |
388 } // namespace remoting | 427 } // namespace remoting |
389 | 428 |
390 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::DecoderTester); | 429 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::DecoderTester); |
OLD | NEW |