| 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 |