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 |