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 // This webpage shows layout of YV12 and other YUV formats | 5 // This webpage shows layout of YV12 and other YUV formats |
6 // http://www.fourcc.org/yuv.php | 6 // http://www.fourcc.org/yuv.php |
7 // The actual conversion is best described here | 7 // The actual conversion is best described here |
8 // http://en.wikipedia.org/wiki/YUV | 8 // http://en.wikipedia.org/wiki/YUV |
9 // An article on optimizing YUV conversion using tables instead of multiplies | 9 // An article on optimizing YUV conversion using tables instead of multiplies |
10 // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf | 10 // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf |
11 // | 11 // |
12 // YV12 is a full plane of Y and a half height, half width chroma planes | 12 // YV12 is a full plane of Y and a half height, half width chroma planes |
13 // YV16 is a full plane of Y and a full height, half width chroma planes | 13 // YV16 is a full plane of Y and a full height, half width chroma planes |
14 // | 14 // |
15 // ARGB pixel format is output, which on little endian is stored as BGRA. | 15 // ARGB pixel format is output, which on little endian is stored as BGRA. |
16 // The alpha is set to 255, allowing the application to use RGBA or RGB32. | 16 // The alpha is set to 255, allowing the application to use RGBA or RGB32. |
17 | 17 |
18 #include "media/base/yuv_convert.h" | 18 #include "media/base/yuv_convert.h" |
19 | 19 |
| 20 #include "base/cpu.h" |
20 #include "base/logging.h" | 21 #include "base/logging.h" |
21 #include "base/memory/scoped_ptr.h" | 22 #include "base/memory/scoped_ptr.h" |
22 #include "build/build_config.h" | 23 #include "build/build_config.h" |
23 #include "media/base/cpu_features.h" | |
24 #include "media/base/simd/convert_rgb_to_yuv.h" | 24 #include "media/base/simd/convert_rgb_to_yuv.h" |
25 #include "media/base/simd/convert_yuv_to_rgb.h" | 25 #include "media/base/simd/convert_yuv_to_rgb.h" |
26 #include "media/base/simd/filter_yuv.h" | 26 #include "media/base/simd/filter_yuv.h" |
27 | 27 |
28 #if defined(ARCH_CPU_X86_FAMILY) | 28 #if defined(ARCH_CPU_X86_FAMILY) |
29 #if defined(COMPILER_MSVC) | 29 #if defined(COMPILER_MSVC) |
30 #include <intrin.h> | 30 #include <intrin.h> |
31 #else | 31 #else |
32 #include <mmintrin.h> | 32 #include <mmintrin.h> |
33 #endif | 33 #endif |
34 #endif | 34 #endif |
35 | 35 |
36 namespace media { | 36 namespace media { |
37 | 37 |
38 static FilterYUVRowsProc ChooseFilterYUVRowsProc() { | 38 static FilterYUVRowsProc ChooseFilterYUVRowsProc() { |
39 #if defined(ARCH_CPU_X86_FAMILY) | 39 #if defined(ARCH_CPU_X86_FAMILY) |
40 if (hasSSE2()) | 40 base::CPU cpu; |
| 41 if (cpu.has_sse2()) |
41 return &FilterYUVRows_SSE2; | 42 return &FilterYUVRows_SSE2; |
42 if (hasMMX()) | 43 if (cpu.has_mmx()) |
43 return &FilterYUVRows_MMX; | 44 return &FilterYUVRows_MMX; |
44 #endif | 45 #endif |
45 return &FilterYUVRows_C; | 46 return &FilterYUVRows_C; |
46 } | 47 } |
47 | 48 |
48 static ConvertYUVToRGB32RowProc ChooseConvertYUVToRGB32RowProc() { | 49 static ConvertYUVToRGB32RowProc ChooseConvertYUVToRGB32RowProc() { |
49 #if defined(ARCH_CPU_X86_FAMILY) | 50 #if defined(ARCH_CPU_X86_FAMILY) |
50 if (hasSSE()) | 51 base::CPU cpu; |
| 52 if (cpu.has_sse()) |
51 return &ConvertYUVToRGB32Row_SSE; | 53 return &ConvertYUVToRGB32Row_SSE; |
52 if (hasMMX()) | 54 if (cpu.has_mmx()) |
53 return &ConvertYUVToRGB32Row_MMX; | 55 return &ConvertYUVToRGB32Row_MMX; |
54 #endif | 56 #endif |
55 return &ConvertYUVToRGB32Row_C; | 57 return &ConvertYUVToRGB32Row_C; |
56 } | 58 } |
57 | 59 |
58 static ScaleYUVToRGB32RowProc ChooseScaleYUVToRGB32RowProc() { | 60 static ScaleYUVToRGB32RowProc ChooseScaleYUVToRGB32RowProc() { |
59 #if defined(ARCH_CPU_X86_64) | 61 #if defined(ARCH_CPU_X86_64) |
60 // Use 64-bits version if possible. | 62 // Use 64-bits version if possible. |
61 return &ScaleYUVToRGB32Row_SSE2_X64; | 63 return &ScaleYUVToRGB32Row_SSE2_X64; |
62 #elif defined(ARCH_CPU_X86_FAMILY) | 64 #elif defined(ARCH_CPU_X86_FAMILY) |
| 65 base::CPU cpu; |
63 // Choose the best one on 32-bits system. | 66 // Choose the best one on 32-bits system. |
64 if (hasSSE()) | 67 if (cpu.has_sse()) |
65 return &ScaleYUVToRGB32Row_SSE; | 68 return &ScaleYUVToRGB32Row_SSE; |
66 if (hasMMX()) | 69 if (cpu.has_mmx()) |
67 return &ScaleYUVToRGB32Row_MMX; | 70 return &ScaleYUVToRGB32Row_MMX; |
68 #endif // defined(ARCH_CPU_X86_64) | 71 #endif // defined(ARCH_CPU_X86_64) |
69 return &ScaleYUVToRGB32Row_C; | 72 return &ScaleYUVToRGB32Row_C; |
70 } | 73 } |
71 | 74 |
72 static ScaleYUVToRGB32RowProc ChooseLinearScaleYUVToRGB32RowProc() { | 75 static ScaleYUVToRGB32RowProc ChooseLinearScaleYUVToRGB32RowProc() { |
73 #if defined(ARCH_CPU_X86_64) | 76 #if defined(ARCH_CPU_X86_64) |
74 // Use 64-bits version if possible. | 77 // Use 64-bits version if possible. |
75 return &LinearScaleYUVToRGB32Row_MMX_X64; | 78 return &LinearScaleYUVToRGB32Row_MMX_X64; |
76 #elif defined(ARCH_CPU_X86_FAMILY) | 79 #elif defined(ARCH_CPU_X86_FAMILY) |
| 80 base::CPU cpu; |
77 // 32-bits system. | 81 // 32-bits system. |
78 if (hasSSE()) | 82 if (cpu.has_sse()) |
79 return &LinearScaleYUVToRGB32Row_SSE; | 83 return &LinearScaleYUVToRGB32Row_SSE; |
80 if (hasMMX()) | 84 if (cpu.has_mmx()) |
81 return &LinearScaleYUVToRGB32Row_MMX; | 85 return &LinearScaleYUVToRGB32Row_MMX; |
82 #endif // defined(ARCH_CPU_X86_64) | 86 #endif // defined(ARCH_CPU_X86_64) |
83 return &LinearScaleYUVToRGB32Row_C; | 87 return &LinearScaleYUVToRGB32Row_C; |
84 } | 88 } |
85 | 89 |
86 // Empty SIMD registers state after using them. | 90 // Empty SIMD registers state after using them. |
87 void EmptyRegisterState() { | 91 void EmptyRegisterState() { |
88 #if defined(ARCH_CPU_X86_FAMILY) | 92 #if defined(ARCH_CPU_X86_FAMILY) |
89 static bool checked = false; | 93 static bool checked = false; |
90 static bool has_mmx = false; | 94 static bool has_mmx = false; |
91 if (!checked) { | 95 if (!checked) { |
92 has_mmx = hasMMX(); | 96 base::CPU cpu; |
| 97 has_mmx = cpu.has_mmx(); |
93 checked = true; | 98 checked = true; |
94 } | 99 } |
95 if (has_mmx) | 100 if (has_mmx) |
96 _mm_empty(); | 101 _mm_empty(); |
97 #endif | 102 #endif |
98 } | 103 } |
99 | 104 |
100 // 16.16 fixed point arithmetic | 105 // 16.16 fixed point arithmetic |
101 const int kFractionBits = 16; | 106 const int kFractionBits = 16; |
102 const int kFractionMax = 1 << kFractionBits; | 107 const int kFractionMax = 1 << kFractionBits; |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, | 443 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, |
439 int, int, int, int, int) = NULL; | 444 int, int, int, int, int) = NULL; |
440 if (!convert_proc) { | 445 if (!convert_proc) { |
441 #if defined(ARCH_CPU_ARM_FAMILY) | 446 #if defined(ARCH_CPU_ARM_FAMILY) |
442 // For ARM processors, always use C version. | 447 // For ARM processors, always use C version. |
443 // TODO(hclam): Implement a NEON version. | 448 // TODO(hclam): Implement a NEON version. |
444 convert_proc = &ConvertRGB32ToYUV_C; | 449 convert_proc = &ConvertRGB32ToYUV_C; |
445 #else | 450 #else |
446 // TODO(hclam): Switch to SSSE3 version when the cyan problem is solved. | 451 // TODO(hclam): Switch to SSSE3 version when the cyan problem is solved. |
447 // See: crbug.com/100462 | 452 // See: crbug.com/100462 |
448 if (hasSSE2()) | 453 base::CPU cpu; |
| 454 if (cpu.has_sse2()) |
449 convert_proc = &ConvertRGB32ToYUV_SSE2; | 455 convert_proc = &ConvertRGB32ToYUV_SSE2; |
450 else | 456 else |
451 convert_proc = &ConvertRGB32ToYUV_C; | 457 convert_proc = &ConvertRGB32ToYUV_C; |
452 #endif | 458 #endif |
453 } | 459 } |
454 | 460 |
455 convert_proc(rgbframe, yplane, uplane, vplane, width, height, | 461 convert_proc(rgbframe, yplane, uplane, vplane, width, height, |
456 rgbstride, ystride, uvstride); | 462 rgbstride, ystride, uvstride); |
457 } | 463 } |
458 | 464 |
459 void ConvertRGB24ToYUV(const uint8* rgbframe, | 465 void ConvertRGB24ToYUV(const uint8* rgbframe, |
460 uint8* yplane, | 466 uint8* yplane, |
461 uint8* uplane, | 467 uint8* uplane, |
462 uint8* vplane, | 468 uint8* vplane, |
463 int width, | 469 int width, |
464 int height, | 470 int height, |
465 int rgbstride, | 471 int rgbstride, |
466 int ystride, | 472 int ystride, |
467 int uvstride) { | 473 int uvstride) { |
468 #if defined(ARCH_CPU_ARM_FAMILY) | 474 #if defined(ARCH_CPU_ARM_FAMILY) |
469 ConvertRGB24ToYUV_C(rgbframe, yplane, uplane, vplane, width, height, | 475 ConvertRGB24ToYUV_C(rgbframe, yplane, uplane, vplane, width, height, |
470 rgbstride, ystride, uvstride); | 476 rgbstride, ystride, uvstride); |
471 #else | 477 #else |
472 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, | 478 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, |
473 int, int, int, int, int) = NULL; | 479 int, int, int, int, int) = NULL; |
474 if (!convert_proc) { | 480 if (!convert_proc) { |
475 if (hasSSSE3()) | 481 base::CPU cpu; |
| 482 if (cpu.has_ssse3()) |
476 convert_proc = &ConvertRGB24ToYUV_SSSE3; | 483 convert_proc = &ConvertRGB24ToYUV_SSSE3; |
477 else | 484 else |
478 convert_proc = &ConvertRGB24ToYUV_C; | 485 convert_proc = &ConvertRGB24ToYUV_C; |
479 } | 486 } |
480 convert_proc(rgbframe, yplane, uplane, vplane, width, height, | 487 convert_proc(rgbframe, yplane, uplane, vplane, width, height, |
481 rgbstride, ystride, uvstride); | 488 rgbstride, ystride, uvstride); |
482 #endif | 489 #endif |
483 } | 490 } |
484 | 491 |
485 void ConvertYUY2ToYUV(const uint8* src, | 492 void ConvertYUY2ToYUV(const uint8* src, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 int ystride, | 541 int ystride, |
535 int uvstride, | 542 int uvstride, |
536 int rgbstride, | 543 int rgbstride, |
537 YUVType yuv_type) { | 544 YUVType yuv_type) { |
538 #if defined(ARCH_CPU_ARM_FAMILY) | 545 #if defined(ARCH_CPU_ARM_FAMILY) |
539 ConvertYUVToRGB32_C(yplane, uplane, vplane, rgbframe, | 546 ConvertYUVToRGB32_C(yplane, uplane, vplane, rgbframe, |
540 width, height, ystride, uvstride, rgbstride, yuv_type); | 547 width, height, ystride, uvstride, rgbstride, yuv_type); |
541 #else | 548 #else |
542 static ConvertYUVToRGB32Proc convert_proc = NULL; | 549 static ConvertYUVToRGB32Proc convert_proc = NULL; |
543 if (!convert_proc) { | 550 if (!convert_proc) { |
544 if (hasSSE()) | 551 base::CPU cpu; |
| 552 if (cpu.has_sse()) |
545 convert_proc = &ConvertYUVToRGB32_SSE; | 553 convert_proc = &ConvertYUVToRGB32_SSE; |
546 else if (hasMMX()) | 554 else if (cpu.has_mmx()) |
547 convert_proc = &ConvertYUVToRGB32_MMX; | 555 convert_proc = &ConvertYUVToRGB32_MMX; |
548 else | 556 else |
549 convert_proc = &ConvertYUVToRGB32_C; | 557 convert_proc = &ConvertYUVToRGB32_C; |
550 } | 558 } |
551 | 559 |
552 convert_proc(yplane, uplane, vplane, rgbframe, | 560 convert_proc(yplane, uplane, vplane, rgbframe, |
553 width, height, ystride, uvstride, rgbstride, yuv_type); | 561 width, height, ystride, uvstride, rgbstride, yuv_type); |
554 #endif | 562 #endif |
555 } | 563 } |
556 | 564 |
557 } // namespace media | 565 } // namespace media |
OLD | NEW |