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

Side by Side Diff: media/base/yuv_convert_unittest.cc

Issue 7003082: Implements RGB to YV12 conversion in YASM. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/base_paths.h" 5 #include "base/base_paths.h"
6 #include "base/file_util.h" 6 #include "base/file_util.h"
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/path_service.h" 8 #include "base/path_service.h"
9 #include "base/stringprintf.h"
9 #include "media/base/djb2.h" 10 #include "media/base/djb2.h"
10 #include "media/base/yuv_convert.h" 11 #include "media/base/yuv_convert.h"
11 #include "media/base/yuv_row.h" 12 #include "media/base/yuv_row.h"
12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
13 14
15 namespace {
16
17 // Reference code that converts RGB pixels to YUV pixels.
18 int ConvertRGBToY(const uint8* rgb) {
19 int y = 25 * rgb[0] + 129 * rgb[1] + 66 * rgb[2];
20 y = ((y + 128) >> 8) + 16;
21 return std::max(0, std::min(255, y));
22 }
23
24 int ConvertRGBToU(const uint8* rgb, int size, bool subsampling) {
25 int u = 0;
26 if (!subsampling) {
27 u = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2];
28 } else {
29 int u0 = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2];
30 int u1 = 112 * rgb[size] - 74 * rgb[size + 1] - 38 * rgb[size + 2];
31 u = (u0 + u1 + 1) / 2;
32 }
33 u = ((u + 128) >> 8) + 128;
34 return std::max(0, std::min(255, u));
35 }
36
37 int ConvertRGBToV(const uint8* rgb, int size, bool subsampling) {
38 int v = 0;
39 if (!subsampling) {
40 v = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2];
41 } else {
42 int v0 = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2];
43 int v1 = -18 * rgb[size] - 94 * rgb[size + 1] + 112 * rgb[size + 2];
44 v = (v0 + v1 + 1) / 2;
45 }
46 v = ((v + 128) >> 8) + 128;
47 return std::max(0, std::min(255, v));
48 }
49
50 // Reference code that converts YUV pixels to RGB pixels.
51 int ConvertYUVToR(uint8 y, uint8 u, uint8 v) {
52 int r = 298 * (y - 16) + 409 * (v - 128);
53 r = (r + 128) >> 8;
54 return std::max(0, std::min(255, r));
55 }
56
57 int ConvertYUVToG(uint8 y, uint8 u, uint8 v) {
58 int g = 298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128);
59 g = (g + 128) >> 8;
60 return std::max(0, std::min(255, g));
61 }
62
63 int ConvertYUVToB(uint8 y, uint8 u, uint8 v) {
64 int b = 298 * (y - 16) + 516 * (u - 128);
65 b = (b + 128) >> 8;
66 return std::max(0, std::min(255, b));
67 }
68
69 } // namespace
70
14 // Size of raw image. 71 // Size of raw image.
15 static const int kSourceWidth = 640; 72 static const int kSourceWidth = 640;
16 static const int kSourceHeight = 360; 73 static const int kSourceHeight = 360;
17 static const int kSourceYSize = kSourceWidth * kSourceHeight; 74 static const int kSourceYSize = kSourceWidth * kSourceHeight;
18 static const int kScaledWidth = 1024; 75 static const int kScaledWidth = 1024;
19 static const int kScaledHeight = 768; 76 static const int kScaledHeight = 768;
20 static const int kBpp = 4; 77 static const int kBpp = 4;
21 78
22 // Surface sizes for various test files. 79 // Surface sizes for various test files.
23 static const int kYUV12Size = kSourceYSize * 12 / 8; 80 static const int kYUV12Size = kSourceYSize * 12 / 8;
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 media::ConvertYUY2ToYUV(yuy_bytes.get(), 344 media::ConvertYUY2ToYUV(yuy_bytes.get(),
288 yuv_converted_bytes.get(), 345 yuv_converted_bytes.get(),
289 yuv_converted_bytes.get() + kSourceYSize, 346 yuv_converted_bytes.get() + kSourceYSize,
290 yuv_converted_bytes.get() + kSourceYSize * 5 / 4, 347 yuv_converted_bytes.get() + kSourceYSize * 5 / 4,
291 kSourceWidth, kSourceHeight); 348 kSourceWidth, kSourceHeight);
292 349
293 uint32 yuy_hash = DJB2Hash(yuv_converted_bytes.get(), kYUV12Size, 350 uint32 yuy_hash = DJB2Hash(yuv_converted_bytes.get(), kYUV12Size,
294 kDJB2HashSeed); 351 kDJB2HashSeed);
295 EXPECT_EQ(666823187u, yuy_hash); 352 EXPECT_EQ(666823187u, yuy_hash);
296 } 353 }
354
355 // A side-by-side test that verifies our ASM functions that convert RGB pixels
356 // to YUV pixels can output the expected results. This test converts RGB pixels
357 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3)
358 // and compare the output YUV pixels with the ones calculated with out reference
359 // functions implemented in C++.
360 TEST(YUVConvertTest, SideBySideRGB) {
Alpha Left Google 2011/09/01 13:26:41 One more comment on these tests, since they test C
361 // This test checks a subset of all RGB values so this test does not take so
362 // long time.
363 const int kStep = 8;
364 const int kWidth = 256 / kStep;
365
366 #ifdef ENABLE_SUBSAMPLING
367 const bool kSubsampling = true;
368 #else
369 const bool kSubsampling = false;
370 #endif
371
372 for (int size = 3; size <= 4; ++size) {
373 // Create the output buffers.
374 scoped_array<uint8> rgb(new uint8[kWidth * size]);
375 scoped_array<uint8> y(new uint8[kWidth]);
376 scoped_array<uint8> u(new uint8[kWidth / 2]);
377 scoped_array<uint8> v(new uint8[kWidth / 2]);
378
379 // Choose the function that converts from RGB pixels to YUV ones.
380 void (*convert)(const uint8*, uint8*, uint8*, uint8*,
381 int, int, int, int, int) = NULL;
382 if (size == 3)
383 convert = media::ConvertRGB24ToYUV;
384 else
385 convert = media::ConvertRGB32ToYUV;
386
387 for (int r = 0; r < kWidth; ++r) {
388 for (int g = 0; g < kWidth; ++g) {
389
390 // Fill the input pixels.
391 for (int b = 0; b < kWidth; ++b) {
392 rgb[b * size + 0] = b * kStep;
393 rgb[b * size + 1] = g * kStep;
394 rgb[b * size + 2] = r * kStep;
395 if (size == 4)
396 rgb[b * size + 3] = 255;
397 }
398
399 // Convert the input RGB pixels to YUV ones.
400 convert(rgb.get(), y.get(), u.get(), v.get(), kWidth, 1, kWidth * size,
401 kWidth, kWidth / 2);
402
403 // Check the output Y pixels.
404 for (int i = 0; i < kWidth; ++i) {
405 const uint8* p = &rgb[i * size];
406 SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
407 EXPECT_EQ(ConvertRGBToY(p), y[i]);
408 }
409
410 // Check the output U pixels.
411 for (int i = 0; i < kWidth / 2; ++i) {
412 const uint8* p = &rgb[i * 2 * size];
413 SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
414 EXPECT_EQ(ConvertRGBToU(p, size, kSubsampling), u[i]);
415 }
416
417 // Check the output V pixels.
418 for (int i = 0; i < kWidth / 2; ++i) {
419 const uint8* p = &rgb[i * 2 * size];
420 SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
421 EXPECT_EQ(ConvertRGBToV(p, size, kSubsampling), v[i]);
422 }
423 }
424 }
425 }
426 }
427
428 // Another side-by-side test for our ASM functions that convert YUV pixels
429 // to RGB pixels.
430 TEST(YUVConvertTest, SideBySideYUV) {
431 const int kStep = 4;
432 const int kWidth = 256 / kStep;
433
434 // Create the output buffers.
435 scoped_array<uint8> rgb(new uint8[kWidth * 4]);
436 scoped_array<uint8> y(new uint8[kWidth]);
437 scoped_array<uint8> u(new uint8[kWidth / 2]);
438 scoped_array<uint8> v(new uint8[kWidth / 2]);
439
440 for (int y0 = 0; y0 < kWidth; ++y0) {
441 for (int i = 0; i < kWidth; ++i)
442 y[i] = y0 * kStep;
443
444 for (int u0 = 0; u0 < kWidth / 2; ++u0) {
445 for (int i = 0; i < kWidth / 2; ++i)
446 u[i] = u0 * kStep * 2;
447
448 for (int v0 = 0; v0 < kWidth / 2; ++v0)
449 v[v0] = v0 * kStep * 2;
450
451 // Convert the input YUV pixels to RGB ones.
452 media::ConvertYUVToRGB32(y.get(), u.get(), v.get(), rgb.get(), kWidth, 1,
453 kWidth, kWidth / 2, kWidth * 4, media::YV12);
454
455 for (int i = 0; i < kWidth; ++i) {
456 SCOPED_TRACE(
457 base::StringPrintf("y=%d,u=%d,v=%d", y[i], u[i / 2], v[i / 2]));
458 EXPECT_EQ(255, rgb[i * 4 + 3]);
459 EXPECT_EQ(ConvertYUVToR(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 2]);
460 EXPECT_EQ(ConvertYUVToG(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 1]);
461 EXPECT_EQ(ConvertYUVToB(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 0]);
462 }
463 }
464 }
465 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698