| 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 <stddef.h> | 20 #include <stddef.h> |
| 21 | 21 |
| 22 #include <algorithm> | 22 #include <algorithm> |
| 23 | 23 |
| 24 #include "base/cpu.h" | 24 #include "base/cpu.h" |
| 25 #include "base/lazy_instance.h" | |
| 26 #include "base/logging.h" | 25 #include "base/logging.h" |
| 27 #include "base/macros.h" | 26 #include "base/macros.h" |
| 28 #include "base/memory/aligned_memory.h" | 27 #include "base/memory/aligned_memory.h" |
| 29 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 28 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 30 #include "build/build_config.h" | 29 #include "build/build_config.h" |
| 31 #include "media/base/simd/convert_rgb_to_yuv.h" | 30 #include "media/base/simd/convert_rgb_to_yuv.h" |
| 32 #include "media/base/simd/convert_yuv_to_rgb.h" | 31 #include "media/base/simd/convert_yuv_to_rgb.h" |
| 33 #include "media/base/simd/filter_yuv.h" | 32 #include "media/base/simd/filter_yuv.h" |
| 34 | 33 |
| 35 #if defined(ARCH_CPU_X86_FAMILY) | 34 #if defined(ARCH_CPU_X86_FAMILY) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 static ConvertYUVToRGB32RowProc g_convert_yuv_to_rgb32_row_proc_ = NULL; | 108 static ConvertYUVToRGB32RowProc g_convert_yuv_to_rgb32_row_proc_ = NULL; |
| 110 static ScaleYUVToRGB32RowProc g_scale_yuv_to_rgb32_row_proc_ = NULL; | 109 static ScaleYUVToRGB32RowProc g_scale_yuv_to_rgb32_row_proc_ = NULL; |
| 111 static ScaleYUVToRGB32RowProc g_linear_scale_yuv_to_rgb32_row_proc_ = NULL; | 110 static ScaleYUVToRGB32RowProc g_linear_scale_yuv_to_rgb32_row_proc_ = NULL; |
| 112 static ConvertRGBToYUVProc g_convert_rgb32_to_yuv_proc_ = NULL; | 111 static ConvertRGBToYUVProc g_convert_rgb32_to_yuv_proc_ = NULL; |
| 113 static ConvertRGBToYUVProc g_convert_rgb24_to_yuv_proc_ = NULL; | 112 static ConvertRGBToYUVProc g_convert_rgb24_to_yuv_proc_ = NULL; |
| 114 static ConvertYUVToRGB32Proc g_convert_yuv_to_rgb32_proc_ = NULL; | 113 static ConvertYUVToRGB32Proc g_convert_yuv_to_rgb32_proc_ = NULL; |
| 115 static ConvertYUVAToARGBProc g_convert_yuva_to_argb_proc_ = NULL; | 114 static ConvertYUVAToARGBProc g_convert_yuva_to_argb_proc_ = NULL; |
| 116 | 115 |
| 117 static const int kYUVToRGBTableSize = 256 * 4 * 4 * sizeof(int16_t); | 116 static const int kYUVToRGBTableSize = 256 * 4 * 4 * sizeof(int16_t); |
| 118 | 117 |
| 119 // base::AlignedMemory has a private operator new(), so wrap it in a struct so | 118 static int16_t* g_table_rec601 = NULL; |
| 120 // that we can put it in a LazyInstance::Leaky. | 119 static int16_t* g_table_jpeg = NULL; |
| 121 struct YUVToRGBTableWrapper { | 120 static int16_t* g_table_rec709 = NULL; |
| 122 base::AlignedMemory<kYUVToRGBTableSize, 16> table; | |
| 123 }; | |
| 124 | |
| 125 typedef base::LazyInstance<YUVToRGBTableWrapper>::Leaky | |
| 126 YUVToRGBTable; | |
| 127 static YUVToRGBTable g_table_rec601 = LAZY_INSTANCE_INITIALIZER; | |
| 128 static YUVToRGBTable g_table_jpeg = LAZY_INSTANCE_INITIALIZER; | |
| 129 static YUVToRGBTable g_table_rec709 = LAZY_INSTANCE_INITIALIZER; | |
| 130 static const int16_t* g_table_rec601_ptr = NULL; | |
| 131 static const int16_t* g_table_jpeg_ptr = NULL; | |
| 132 static const int16_t* g_table_rec709_ptr = NULL; | |
| 133 | 121 |
| 134 // Empty SIMD registers state after using them. | 122 // Empty SIMD registers state after using them. |
| 135 void EmptyRegisterStateStub() {} | 123 void EmptyRegisterStateStub() {} |
| 136 #if defined(MEDIA_MMX_INTRINSICS_AVAILABLE) | 124 #if defined(MEDIA_MMX_INTRINSICS_AVAILABLE) |
| 137 void EmptyRegisterStateIntrinsic() { _mm_empty(); } | 125 void EmptyRegisterStateIntrinsic() { _mm_empty(); } |
| 138 #endif | 126 #endif |
| 139 typedef void (*EmptyRegisterStateProc)(); | 127 typedef void (*EmptyRegisterStateProc)(); |
| 140 static EmptyRegisterStateProc g_empty_register_state_proc_ = NULL; | 128 static EmptyRegisterStateProc g_empty_register_state_proc_ = NULL; |
| 141 | 129 |
| 142 // Get the appropriate value to bitshift by for vertical indices. | 130 // Get the appropriate value to bitshift by for vertical indices. |
| 143 int GetVerticalShift(YUVType type) { | 131 int GetVerticalShift(YUVType type) { |
| 144 switch (type) { | 132 switch (type) { |
| 145 case YV16: | 133 case YV16: |
| 146 return 0; | 134 return 0; |
| 147 case YV12: | 135 case YV12: |
| 148 case YV12J: | 136 case YV12J: |
| 149 case YV12HD: | 137 case YV12HD: |
| 150 return 1; | 138 return 1; |
| 151 } | 139 } |
| 152 NOTREACHED(); | 140 NOTREACHED(); |
| 153 return 0; | 141 return 0; |
| 154 } | 142 } |
| 155 | 143 |
| 156 const int16_t* GetLookupTable(YUVType type) { | 144 const int16_t* GetLookupTable(YUVType type) { |
| 157 switch (type) { | 145 switch (type) { |
| 158 case YV12: | 146 case YV12: |
| 159 case YV16: | 147 case YV16: |
| 160 return g_table_rec601_ptr; | 148 return g_table_rec601; |
| 161 case YV12J: | 149 case YV12J: |
| 162 return g_table_jpeg_ptr; | 150 return g_table_jpeg; |
| 163 case YV12HD: | 151 case YV12HD: |
| 164 return g_table_rec709_ptr; | 152 return g_table_rec709; |
| 165 } | 153 } |
| 166 NOTREACHED(); | 154 NOTREACHED(); |
| 167 return NULL; | 155 return NULL; |
| 168 } | 156 } |
| 169 | 157 |
| 170 // Populates a pre-allocated lookup table from a YUV->RGB matrix. | 158 // Populates a pre-allocated lookup table from a YUV->RGB matrix. |
| 171 const int16_t* PopulateYUVToRGBTable(const double matrix[3][3], | 159 const int16_t* PopulateYUVToRGBTable(const double matrix[3][3], |
| 172 bool full_range, | 160 bool full_range, |
| 173 int16_t* table) { | 161 int16_t* table) { |
| 174 // We'll have 4 sub-tables that lie contiguous in memory, one for each of Y, | 162 // We'll have 4 sub-tables that lie contiguous in memory, one for each of Y, |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 const double kJPEGConvertMatrix[3][3] = { | 282 const double kJPEGConvertMatrix[3][3] = { |
| 295 {1.0, 1.0, 1.0}, {0.0, -0.34414, 1.772}, {1.402, -0.71414, 0.0}, | 283 {1.0, 1.0, 1.0}, {0.0, -0.34414, 1.772}, {1.402, -0.71414, 0.0}, |
| 296 }; | 284 }; |
| 297 | 285 |
| 298 // Rec709 "HD" color space, values from: | 286 // Rec709 "HD" color space, values from: |
| 299 // http://www.equasys.de/colorconversion.html | 287 // http://www.equasys.de/colorconversion.html |
| 300 const double kRec709ConvertMatrix[3][3] = { | 288 const double kRec709ConvertMatrix[3][3] = { |
| 301 {1.164, 1.164, 1.164}, {0.0, -0.213, 2.112}, {1.793, -0.533, 0.0}, | 289 {1.164, 1.164, 1.164}, {0.0, -0.213, 2.112}, {1.793, -0.533, 0.0}, |
| 302 }; | 290 }; |
| 303 | 291 |
| 304 PopulateYUVToRGBTable(kRec601ConvertMatrix, false, | 292 g_table_rec601 = |
| 305 g_table_rec601.Get().table.data_as<int16_t>()); | 293 static_cast<int16_t*>(base::AlignedAlloc(kYUVToRGBTableSize, 16)); |
| 306 PopulateYUVToRGBTable(kJPEGConvertMatrix, true, | 294 PopulateYUVToRGBTable(kRec601ConvertMatrix, false, g_table_rec601); |
| 307 g_table_jpeg.Get().table.data_as<int16_t>()); | 295 |
| 308 PopulateYUVToRGBTable(kRec709ConvertMatrix, false, | 296 g_table_rec709 = |
| 309 g_table_rec709.Get().table.data_as<int16_t>()); | 297 static_cast<int16_t*>(base::AlignedAlloc(kYUVToRGBTableSize, 16)); |
| 310 g_table_rec601_ptr = g_table_rec601.Get().table.data_as<int16_t>(); | 298 PopulateYUVToRGBTable(kRec709ConvertMatrix, false, g_table_rec709); |
| 311 g_table_rec709_ptr = g_table_rec709.Get().table.data_as<int16_t>(); | 299 |
| 312 g_table_jpeg_ptr = g_table_jpeg.Get().table.data_as<int16_t>(); | 300 g_table_jpeg = |
| 301 static_cast<int16_t*>(base::AlignedAlloc(kYUVToRGBTableSize, 16)); |
| 302 PopulateYUVToRGBTable(kJPEGConvertMatrix, true, g_table_jpeg); |
| 313 } | 303 } |
| 314 | 304 |
| 315 // Empty SIMD registers state after using them. | 305 // Empty SIMD registers state after using them. |
| 316 void EmptyRegisterState() { g_empty_register_state_proc_(); } | 306 void EmptyRegisterState() { g_empty_register_state_proc_(); } |
| 317 | 307 |
| 318 // 16.16 fixed point arithmetic | 308 // 16.16 fixed point arithmetic |
| 319 const int kFractionBits = 16; | 309 const int kFractionBits = 16; |
| 320 const int kFractionMax = 1 << kFractionBits; | 310 const int kFractionMax = 1 << kFractionBits; |
| 321 const int kFractionMask = ((1 << kFractionBits) - 1); | 311 const int kFractionMask = ((1 << kFractionBits) - 1); |
| 322 | 312 |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 width, | 725 width, |
| 736 height, | 726 height, |
| 737 ystride, | 727 ystride, |
| 738 uvstride, | 728 uvstride, |
| 739 astride, | 729 astride, |
| 740 rgbstride, | 730 rgbstride, |
| 741 yuv_type); | 731 yuv_type); |
| 742 } | 732 } |
| 743 | 733 |
| 744 } // namespace media | 734 } // namespace media |
| OLD | NEW |