OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 | 140 |
141 if (result == Decoder::DECODE_DONE) { | 141 if (result == Decoder::DECODE_DONE) { |
142 decoder_->RenderFrame(SkISize::Make(kWidth, kHeight), | 142 decoder_->RenderFrame(SkISize::Make(kWidth, kHeight), |
143 SkIRect::MakeXYWH(0, 0, kWidth, kHeight), | 143 SkIRect::MakeXYWH(0, 0, kWidth, kHeight), |
144 image_data_.get(), | 144 image_data_.get(), |
145 kWidth * kBytesPerPixel, | 145 kWidth * kBytesPerPixel, |
146 &update_region_); | 146 &update_region_); |
147 } | 147 } |
148 } | 148 } |
149 | 149 |
150 void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) { | |
151 ReceivedPacket(packet.get()); | |
152 } | |
153 | |
150 void set_strict(bool strict) { | 154 void set_strict(bool strict) { |
151 strict_ = strict; | 155 strict_ = strict; |
152 } | 156 } |
153 | 157 |
154 void set_capture_data(scoped_refptr<CaptureData> data) { | 158 void set_capture_data(scoped_refptr<CaptureData> data) { |
155 capture_data_ = data; | 159 capture_data_ = data; |
156 } | 160 } |
157 | 161 |
158 void AddRects(const SkIRect* rects, int count) { | 162 void AddRects(const SkIRect* rects, int count) { |
159 SkRegion new_rects; | 163 SkRegion new_rects; |
160 new_rects.setRects(rects, count); | 164 new_rects.setRects(rects, count); |
161 expected_region_.op(new_rects, SkRegion::kUnion_Op); | 165 AddRegion(new_rects); |
166 } | |
167 | |
168 void AddRegion(const SkRegion& region) { | |
169 expected_region_.op(region, SkRegion::kUnion_Op); | |
162 } | 170 } |
163 | 171 |
164 void VerifyResults() { | 172 void VerifyResults() { |
165 if (!strict_) | 173 if (!strict_) |
166 return; | 174 return; |
167 | 175 |
168 ASSERT_TRUE(capture_data_.get()); | 176 ASSERT_TRUE(capture_data_.get()); |
169 | 177 |
170 // Test the content of the update region. | 178 // Test the content of the update region. |
171 EXPECT_EQ(expected_region_, update_region_); | 179 EXPECT_EQ(expected_region_, update_region_); |
172 for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) { | 180 for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) { |
173 const int stride = kWidth * kBytesPerPixel; | 181 const int stride = kWidth * kBytesPerPixel; |
174 EXPECT_EQ(stride, capture_data_->data_planes().strides[0]); | 182 EXPECT_EQ(stride, capture_data_->data_planes().strides[0]); |
175 const int offset = stride * i.rect().top() + | 183 const int offset = stride * i.rect().top() + |
176 kBytesPerPixel * i.rect().left(); | 184 kBytesPerPixel * i.rect().left(); |
177 const uint8* original = capture_data_->data_planes().data[0] + offset; | 185 const uint8* original = capture_data_->data_planes().data[0] + offset; |
178 const uint8* decoded = image_data_.get() + offset; | 186 const uint8* decoded = image_data_.get() + offset; |
179 const int row_size = kBytesPerPixel * i.rect().width(); | 187 const int row_size = kBytesPerPixel * i.rect().width(); |
180 for (int y = 0; y < i.rect().height(); ++y) { | 188 for (int y = 0; y < i.rect().height(); ++y) { |
181 EXPECT_EQ(0, memcmp(original, decoded, row_size)) | 189 EXPECT_EQ(0, memcmp(original, decoded, row_size)) |
182 << "Row " << y << " is different"; | 190 << "Row " << y << " is different"; |
183 original += stride; | 191 original += stride; |
184 decoded += stride; | 192 decoded += stride; |
185 } | 193 } |
186 } | 194 } |
187 } | 195 } |
188 | 196 |
197 void VerifyResultsApprox(double max_error_limit, double mean_error_limit) { | |
198 ASSERT_TRUE(capture_data_.get()); | |
199 | |
200 // Test the content of the update region. | |
201 EXPECT_EQ(expected_region_, update_region_); | |
202 double max_error = 0.0; | |
203 double sum_error = 0.0; | |
204 int error_num = 0; | |
205 for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) { | |
206 const int stride = kWidth * kBytesPerPixel; | |
207 EXPECT_EQ(stride, capture_data_->data_planes().strides[0]); | |
208 const int offset = stride * i.rect().top() + | |
209 kBytesPerPixel * i.rect().left(); | |
210 const uint8* original = capture_data_->data_planes().data[0] + offset; | |
211 const uint8* decoded = image_data_.get() + offset; | |
212 for (int y = 0; y < i.rect().height(); ++y) { | |
213 for (int x = 0; x < i.rect().width(); ++x) { | |
214 for (int i = 0; i < 3; i++) { | |
215 UpdateErrorMetrics(original, decoded, max_error, sum_error, | |
Sergey Ulanov
2012/07/26 04:00:17
PSNR is a standard metric that is used to measure
| |
216 error_num); | |
217 original++; | |
218 decoded++; | |
219 } | |
220 original++; | |
221 decoded++; | |
222 } | |
223 } | |
224 } | |
225 EXPECT_LE(max_error, max_error_limit); | |
226 double mean_error = sum_error / error_num; | |
227 EXPECT_LE(mean_error, mean_error_limit); | |
228 LOG(INFO) << "Max error: " << max_error; | |
229 LOG(INFO) << "Mean error: " << mean_error; | |
230 } | |
231 | |
189 private: | 232 private: |
190 bool strict_; | 233 bool strict_; |
191 SkRegion expected_region_; | 234 SkRegion expected_region_; |
192 SkRegion update_region_; | 235 SkRegion update_region_; |
193 Decoder* decoder_; | 236 Decoder* decoder_; |
194 scoped_array<uint8> image_data_; | 237 scoped_array<uint8> image_data_; |
195 scoped_refptr<CaptureData> capture_data_; | 238 scoped_refptr<CaptureData> capture_data_; |
196 | 239 |
240 void UpdateErrorMetrics(const uint8* p1, const uint8* p2, | |
241 double& max_error, double& sum_error, | |
242 int& error_num) { | |
243 double error = | |
244 std::abs(static_cast<int>(*p1) - static_cast<int>(*p2)) / 255.0; | |
245 max_error = std::max(max_error, error); | |
246 sum_error += error; | |
247 error_num++; | |
248 } | |
249 | |
197 DISALLOW_COPY_AND_ASSIGN(DecoderTester); | 250 DISALLOW_COPY_AND_ASSIGN(DecoderTester); |
198 }; | 251 }; |
199 | 252 |
200 // The EncoderTester provides a hook for retrieving the data, and passing the | 253 // The EncoderTester provides a hook for retrieving the data, and passing the |
201 // message to other subprograms for validaton. | 254 // message to other subprograms for validaton. |
202 class EncoderTester { | 255 class EncoderTester { |
203 public: | 256 public: |
204 EncoderTester(EncoderMessageTester* message_tester) | 257 EncoderTester(EncoderMessageTester* message_tester) |
205 : message_tester_(message_tester), | 258 : message_tester_(message_tester), |
206 decoder_tester_(NULL), | 259 decoder_tester_(NULL), |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, | 394 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, |
342 kTestRects, 1); | 395 kTestRects, 1); |
343 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, | 396 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, |
344 kTestRects + 1, 1); | 397 kTestRects + 1, 1); |
345 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, | 398 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, |
346 kTestRects + 2, 1); | 399 kTestRects + 2, 1); |
347 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, | 400 TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, data, |
348 kTestRects + 3, 2); | 401 kTestRects + 3, 2); |
349 } | 402 } |
350 | 403 |
404 static void FillWithGradient(uint8* memory, const SkISize& frame_size, | |
405 const SkIRect& rect) { | |
406 for (int j = rect.top(); j < rect.bottom(); ++j) { | |
407 for (int i = rect.left(); i < rect.right(); ++i) { | |
408 uint8* p = memory + ((j * frame_size.width()) + i) * 4; | |
409 *p++ = static_cast<uint8>((255.0 * i) / frame_size.width()); | |
410 *p++ = static_cast<uint8>((164.0 * j) / frame_size.height()); | |
411 *p++ = static_cast<uint8>((82.0 * (i + j)) / | |
412 (frame_size.width() + frame_size.height())); | |
413 *p++ = 0; | |
414 } | |
415 } | |
416 } | |
417 | |
418 void TestEncoderDecoderGradient(Encoder* encoder, Decoder* decoder, | |
419 double max_error_limit, | |
420 double mean_error_limit) { | |
421 SkIRect full_frame = SkIRect::MakeWH(kWidth, kHeight); | |
422 scoped_array<uint8> frame_data(new uint8[kWidth * kHeight * kBytesPerPixel]); | |
423 FillWithGradient(frame_data.get(), SkISize::Make(kWidth, kHeight), | |
424 full_frame); | |
425 | |
426 DataPlanes planes; | |
427 memset(planes.data, 0, sizeof(planes.data)); | |
428 memset(planes.strides, 0, sizeof(planes.strides)); | |
429 planes.data[0] = frame_data.get(); | |
430 planes.strides[0] = kWidth * kBytesPerPixel; | |
431 | |
432 scoped_refptr<CaptureData> capture_data = | |
433 new CaptureData(planes, SkISize::Make(kWidth, kHeight), | |
434 media::VideoFrame::RGB32); | |
435 capture_data->mutable_dirty_region().op(full_frame, SkRegion::kUnion_Op); | |
436 | |
437 DecoderTester decoder_tester(decoder); | |
438 decoder_tester.set_capture_data(capture_data); | |
439 decoder_tester.AddRegion(capture_data->dirty_region()); | |
440 | |
441 encoder->Encode(capture_data, true, | |
442 base::Bind(&DecoderTester::ReceivedScopedPacket, | |
443 base::Unretained(&decoder_tester))); | |
444 | |
445 decoder_tester.VerifyResultsApprox(max_error_limit, mean_error_limit); | |
446 } | |
447 | |
351 } // namespace remoting | 448 } // namespace remoting |
OLD | NEW |