Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: remoting/base/codec_test.cc

Issue 3011010: Unit test for Encoder / Decoder for remoting (Closed)
Patch Set: fixed comments Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/base/codec_test.h ('k') | remoting/base/decoder_verbatim.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
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"
11 #include "remoting/base/encoder.h"
12 #include "remoting/base/mock_objects.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 static const int kWidth = 320;
16 static const int kHeight = 240;
17 static const int kBytesPerPixel = 4;
18
19 // Some sample rects for testing.
20 static const gfx::Rect kTestRects[] = {
21 gfx::Rect(0, 0, kWidth, kHeight),
22 gfx::Rect(0, 0, kWidth / 2, kHeight / 2),
23 gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
24 gfx::Rect(16, 16, 16, 16),
25 gfx::Rect(128, 64, 32, 32)
26 };
27
28 namespace remoting {
29
30 // A class to test that the state transition of the Encoder is correct.
31 class EncoderStateTester {
32 public:
33 EncoderStateTester()
34 : next_state_(Encoder::EncodingStarting) {
35 }
36
37 ~EncoderStateTester() {
38 EXPECT_EQ(Encoder::EncodingStarting, next_state_);
39 }
40
41 // Set the state output of the Encoder.
42 void ReceivedState(Encoder::EncodingState state) {
43 if (state & Encoder::EncodingStarting) {
44 EXPECT_EQ(Encoder::EncodingStarting, next_state_);
45 next_state_ = Encoder::EncodingInProgress | Encoder::EncodingEnded;
46 } else {
47 EXPECT_FALSE(next_state_ & Encoder::EncodingStarting);
48 }
49
50 if (state & Encoder::EncodingInProgress) {
51 EXPECT_TRUE(next_state_ & Encoder::EncodingInProgress);
52 }
53
54 if (state & Encoder::EncodingEnded) {
55 EXPECT_TRUE(next_state_ & Encoder::EncodingEnded);
56 next_state_ = Encoder::EncodingStarting;
57 }
58 }
59
60 private:
61 Encoder::EncodingState next_state_;
62
63 DISALLOW_COPY_AND_ASSIGN(EncoderStateTester);
64 };
65
66 // A class to test the message output of the encoder.
67 class EncoderMessageTester {
68 public:
69 EncoderMessageTester()
70 : begin_rect_(0),
71 rect_data_(0),
72 end_rect_(0),
73 state_(kWaitingForBeginRect),
74 strict_(false) {
75 }
76
77 ~EncoderMessageTester() {
78 EXPECT_EQ(begin_rect_, end_rect_);
79 EXPECT_EQ(kWaitingForBeginRect, state_);
80 }
81
82 // Test that we received the correct message.
83 void ReceivedMessage(HostMessage* message) {
84 EXPECT_TRUE(message->has_update_stream_packet());
85
86 if (state_ == kWaitingForBeginRect) {
87 EXPECT_TRUE(message->update_stream_packet().has_begin_rect());
88 state_ = kWaitingForRectData;
89 ++begin_rect_;
90
91 if (strict_) {
92 gfx::Rect rect = rects_.front();
93 rects_.pop_front();
94 EXPECT_EQ(rect.x(), message->update_stream_packet().begin_rect().x());
95 EXPECT_EQ(rect.y(), message->update_stream_packet().begin_rect().y());
96 EXPECT_EQ(rect.width(),
97 message->update_stream_packet().begin_rect().width());
98 EXPECT_EQ(rect.height(),
99 message->update_stream_packet().begin_rect().height());
100 }
101 } else {
102 EXPECT_FALSE(message->update_stream_packet().has_begin_rect());
103 }
104
105 if (state_ == kWaitingForRectData) {
106 if (message->update_stream_packet().has_rect_data()) {
107 ++rect_data_;
108 }
109
110 if (message->update_stream_packet().has_end_rect()) {
111 // Expect that we have received some data.
112 EXPECT_GT(rect_data_, 0);
113 rect_data_ = 0;
114 state_ = kWaitingForBeginRect;
115 ++end_rect_;
116 }
117 }
118 }
119
120 void set_strict(bool strict) {
121 strict_ = strict;
122 }
123
124 void AddRects(const gfx::Rect* rects, int count) {
125 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
126 }
127
128 private:
129 enum State {
130 kWaitingForBeginRect,
131 kWaitingForRectData,
132 };
133
134 int begin_rect_;
135 int rect_data_;
136 int end_rect_;
137 State state_;
138 bool strict_;
139
140 std::deque<gfx::Rect> rects_;
141
142 DISALLOW_COPY_AND_ASSIGN(EncoderMessageTester);
143 };
144
145 class DecoderTester {
146 public:
147 DecoderTester(Decoder* decoder)
148 : strict_(false),
149 decoder_(decoder),
150 decode_done_(false) {
151 media::VideoFrame::CreateFrame(media::VideoFrame::RGB32,
152 kWidth, kHeight,
153 base::TimeDelta(),
154 base::TimeDelta(), &frame_);
155 EXPECT_TRUE(frame_.get());
156 }
157
158 void ReceivedMessage(HostMessage* message) {
159 if (message->has_begin_update_stream()) {
160 delete message;
161 decoder_->BeginDecode(
162 frame_, &update_rects_,
163 NewRunnableMethod(this, &DecoderTester::OnPartialDecodeDone),
164 NewRunnableMethod(this, &DecoderTester::OnDecodeDone));
165 }
166
167 if (message->has_update_stream_packet()) {
168 decoder_->PartialDecode(message);
169 }
170
171 if (message->has_end_update_stream()) {
172 delete message;
173 decoder_->EndDecode();
174 }
175 }
176
177 void set_strict(bool strict) {
178 strict_ = strict;
179 }
180
181 void set_capture_data(scoped_refptr<CaptureData> data) {
182 capture_data_ = data;
183 }
184
185 void AddRects(const gfx::Rect* rects, int count) {
186 rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
187 }
188
189 bool decode_done() const { return decode_done_; }
190 void reset_decode_done() { decode_done_ = false; }
191
192 private:
193 void OnPartialDecodeDone() {
194 if (!strict_)
195 return;
196 for (size_t i = 0; i < update_rects_.size(); ++i) {
197 EXPECT_FALSE(rects_.empty());
198 gfx::Rect rect = rects_.front();
199 rects_.pop_front();
200 EXPECT_EQ(rect, update_rects_[i]);
201 }
202 }
203
204 void OnDecodeDone() {
205 decode_done_ = true;
206 if (!strict_)
207 return;
208
209 EXPECT_TRUE(capture_data_.get());
210 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) {
211 if (!frame_->data(i) || !capture_data_->data_planes().data[i])
212 continue;
213 // TODO(hclam): HAndle YUV.
214 int size = capture_data_->data_planes().strides[i] * kHeight;
215 EXPECT_EQ(0, memcmp(capture_data_->data_planes().data[i],
216 frame_->data(i), size));
217 }
218 }
219
220 bool strict_;
221 std::deque<gfx::Rect> rects_;
222 UpdatedRects update_rects_;
223 Decoder* decoder_;
224 scoped_refptr<media::VideoFrame> frame_;
225 scoped_refptr<CaptureData> capture_data_;
226 bool decode_done_;
227
228 DISALLOW_COPY_AND_ASSIGN(DecoderTester);
229 };
230
231 class EncoderTester {
232 public:
233 EncoderTester(EncoderMessageTester* message_tester,
234 EncoderStateTester* state_tester)
235 : message_tester_(message_tester),
236 state_tester_(state_tester),
237 data_available_(0) {
238 }
239
240 ~EncoderTester() {
241 EXPECT_GT(data_available_, 0);
242 }
243
244 void DataAvailable(HostMessage* message,
245 Encoder::EncodingState state) {
246 ++data_available_;
247 message_tester_->ReceivedMessage(message);
248 state_tester_->ReceivedState(state);
249
250 // Send the message to the DecoderTester.
251 if (decoder_tester_) {
252 if (state & Encoder::EncodingStarting) {
253 HostMessage* begin_update = new HostMessage();
254 begin_update->mutable_begin_update_stream();
255 decoder_tester_->ReceivedMessage(begin_update);
256 }
257
258 if (state & Encoder::EncodingInProgress) {
259 decoder_tester_->ReceivedMessage(message);
260 }
261
262 if (state & Encoder::EncodingEnded) {
263 HostMessage* end_update = new HostMessage();
264 end_update->mutable_end_update_stream();
265 decoder_tester_->ReceivedMessage(end_update);
266 }
267 return;
268 }
269 delete message;
270 }
271
272 void AddRects(const gfx::Rect* rects, int count) {
273 message_tester_->AddRects(rects, count);
274 }
275
276 void set_decoder_tester(DecoderTester* decoder_tester) {
277 decoder_tester_ = decoder_tester;
278 }
279
280 private:
281 EncoderMessageTester* message_tester_;
282 EncoderStateTester* state_tester_;
283 DecoderTester* decoder_tester_;
284 int data_available_;
285
286 DISALLOW_COPY_AND_ASSIGN(EncoderTester);
287 };
288
289 scoped_refptr<CaptureData> PrepareEncodeData(PixelFormat format,
290 uint8** memory) {
291 // TODO(hclam): Support also YUV format.
292 CHECK(format == PixelFormatRgb32);
293 int size = kWidth * kHeight * kBytesPerPixel;
294
295 *memory = new uint8[size];
296 srand(0);
297 for (int i = 0; i < size; ++i) {
298 (*memory)[i] = rand() % 256;
299 }
300
301 DataPlanes planes;
302 memset(planes.data, 0, sizeof(planes.data));
303 memset(planes.strides, 0, sizeof(planes.strides));
304 planes.data[0] = *memory;
305 planes.strides[0] = kWidth * kBytesPerPixel;
306
307 scoped_refptr<CaptureData> data =
308 new CaptureData(planes, kWidth, kHeight, format);
309 return data;
310 }
311
312 static void TestEncodingRects(Encoder* encoder,
313 EncoderTester* tester,
314 scoped_refptr<CaptureData> data,
315 const gfx::Rect* rects, int count) {
316 data->mutable_dirty_rects().clear();
317 data->mutable_dirty_rects().insert(
318 data->mutable_dirty_rects().begin(), rects, rects + count);
319 tester->AddRects(rects, count);
320
321 encoder->Encode(data, true,
322 NewCallback(tester, &EncoderTester::DataAvailable));
323 }
324
325 void TestEncoder(Encoder* encoder, bool strict) {
326 EncoderMessageTester message_tester;
327 message_tester.set_strict(strict);
328
329 EncoderStateTester state_tester;
330 EncoderTester tester(&message_tester, &state_tester);
331
332 uint8* memory;
333 scoped_refptr<CaptureData> data =
334 PrepareEncodeData(PixelFormatRgb32, &memory);
335
336 TestEncodingRects(encoder, &tester, data, kTestRects, 1);
337 TestEncodingRects(encoder, &tester, data, kTestRects + 1, 1);
338 TestEncodingRects(encoder, &tester, data, kTestRects + 2, 1);
339 TestEncodingRects(encoder, &tester, data, kTestRects + 3, 2);
340 delete memory;
341 }
342
343 static void TestEncodingRects(Encoder* encoder,
344 EncoderTester* encoder_tester,
345 DecoderTester* decoder_tester,
346 scoped_refptr<CaptureData> data,
347 const gfx::Rect* rects, int count) {
348 data->mutable_dirty_rects().clear();
349 data->mutable_dirty_rects().insert(
350 data->mutable_dirty_rects().begin(), rects, rects + count);
351 encoder_tester->AddRects(rects, count);
352 decoder_tester->AddRects(rects, count);
353 decoder_tester->reset_decode_done();
354
355 encoder->Encode(data, true,
356 NewCallback(encoder_tester, &EncoderTester::DataAvailable));
357 EXPECT_TRUE(decoder_tester->decode_done());
358 }
359
360 void TestEncoderDecoder(Encoder* encoder, Decoder* decoder, bool strict) {
361 EncoderMessageTester message_tester;
362 message_tester.set_strict(strict);
363
364 EncoderStateTester state_tester;
365 EncoderTester encoder_tester(&message_tester, &state_tester);
366
367 uint8* memory;
368 scoped_refptr<CaptureData> data =
369 PrepareEncodeData(PixelFormatRgb32, &memory);
370 DecoderTester decoder_tester(decoder);
371 decoder_tester.set_strict(strict);
372 decoder_tester.set_capture_data(data);
373 encoder_tester.set_decoder_tester(&decoder_tester);
374
375 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
376 kTestRects, 1);
377 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
378 kTestRects + 1, 1);
379 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
380 kTestRects + 2, 1);
381 TestEncodingRects(encoder, &encoder_tester, &decoder_tester, data,
382 kTestRects + 3, 2);
383 delete memory;
384 }
385
386 } // namespace remoting
387
388 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::DecoderTester);
OLDNEW
« no previous file with comments | « remoting/base/codec_test.h ('k') | remoting/base/decoder_verbatim.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698