| OLD | NEW |
| 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 // 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/logging.h" |
| 20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 21 #include "media/base/cpu_features.h" | 22 #include "media/base/cpu_features.h" |
| 22 #include "media/base/simd/convert_rgb_to_yuv.h" | 23 #include "media/base/simd/convert_rgb_to_yuv.h" |
| 24 #include "media/base/simd/convert_yuv_to_rgb.h" |
| 25 #include "media/base/simd/filter_yuv.h" |
| 23 #include "media/base/yuv_convert_internal.h" | 26 #include "media/base/yuv_convert_internal.h" |
| 24 #include "media/base/yuv_row.h" | 27 #include "media/base/yuv_row.h" |
| 25 | 28 |
| 26 #if USE_MMX | 29 #if defined(ARCH_CPU_X86_FAMILY) |
| 27 #if defined(_MSC_VER) | 30 #if defined(COMPILER_MSVC) |
| 28 #include <intrin.h> | 31 #include <intrin.h> |
| 29 #else | 32 #else |
| 30 #include <mmintrin.h> | 33 #include <mmintrin.h> |
| 31 #endif | 34 #endif |
| 32 #endif | 35 #endif |
| 33 | 36 |
| 34 #if USE_SSE2 | 37 namespace media { |
| 35 #include <emmintrin.h> | 38 |
| 39 static FilterYUVRowsProc ChooseFilterYUVRowsProc() { |
| 40 #if defined(ARCH_CPU_X86_FAMILY) |
| 41 if (hasSSE2()) |
| 42 return &FilterYUVRows_SSE2; |
| 43 if (hasMMX()) |
| 44 return &FilterYUVRows_MMX; |
| 36 #endif | 45 #endif |
| 46 return &FilterYUVRows_C; |
| 47 } |
| 37 | 48 |
| 38 namespace media { | 49 static ConvertYUVToRGB32RowProc ChooseConvertYUVToRGB32RowProc() { |
| 50 #if defined(ARCH_CPU_X86_FAMILY) |
| 51 if (hasSSE()) |
| 52 return &ConvertYUVToRGB32Row_SSE; |
| 53 if (hasMMX()) |
| 54 return &ConvertYUVToRGB32Row_MMX; |
| 55 #endif |
| 56 return &ConvertYUVToRGB32Row_C; |
| 57 } |
| 58 |
| 59 static ScaleYUVToRGB32RowProc ChooseScaleYUVToRGB32RowProc() { |
| 60 #if defined(ARCH_CPU_X86_FAMILY) |
| 61 #if defined(ARCH_CPU_X86_64) |
| 62 // Use 64-bits version if possible. |
| 63 return &ScaleYUVToRGB32Row_SSE2_X64; |
| 64 #endif |
| 65 // Choose the best one on 32-bits system. |
| 66 if (hasSSE()) |
| 67 return &ScaleYUVToRGB32Row_SSE; |
| 68 if (hasMMX()) |
| 69 return &ScaleYUVToRGB32Row_MMX; |
| 70 #endif |
| 71 return &ScaleYUVToRGB32Row_C; |
| 72 } |
| 73 |
| 74 static ScaleYUVToRGB32RowProc ChooseLinearScaleYUVToRGB32RowProc() { |
| 75 #if defined(ARCH_CPU_X86_FAMILY) |
| 76 #if defined(ARCH_CPU_X86_64) |
| 77 // Use 64-bits version if possible. |
| 78 return &LinearScaleYUVToRGB32Row_MMX_X64; |
| 79 #endif |
| 80 // 32-bits system. |
| 81 if (hasSSE()) |
| 82 return &LinearScaleYUVToRGB32Row_SSE; |
| 83 if (hasMMX()) |
| 84 return &LinearScaleYUVToRGB32Row_MMX; |
| 85 #endif |
| 86 return &LinearScaleYUVToRGB32Row_C; |
| 87 } |
| 88 |
| 89 // Empty SIMD registers state after using them. |
| 90 void EmptyRegisterState() { |
| 91 #if defined(ARCH_CPU_X86_FAMILY) |
| 92 static bool checked = false; |
| 93 static bool has_mmx = false; |
| 94 if (!checked) { |
| 95 has_mmx = hasMMX(); |
| 96 checked = true; |
| 97 } |
| 98 if (has_mmx) |
| 99 _mm_empty(); |
| 100 #endif |
| 101 } |
| 39 | 102 |
| 40 // 16.16 fixed point arithmetic | 103 // 16.16 fixed point arithmetic |
| 41 const int kFractionBits = 16; | 104 const int kFractionBits = 16; |
| 42 const int kFractionMax = 1 << kFractionBits; | 105 const int kFractionMax = 1 << kFractionBits; |
| 43 const int kFractionMask = ((1 << kFractionBits) - 1); | 106 const int kFractionMask = ((1 << kFractionBits) - 1); |
| 44 | 107 |
| 45 // Convert a frame of YUV to 32 bit ARGB. | |
| 46 void ConvertYUVToRGB32(const uint8* y_buf, | |
| 47 const uint8* u_buf, | |
| 48 const uint8* v_buf, | |
| 49 uint8* rgb_buf, | |
| 50 int width, | |
| 51 int height, | |
| 52 int y_pitch, | |
| 53 int uv_pitch, | |
| 54 int rgb_pitch, | |
| 55 YUVType yuv_type) { | |
| 56 unsigned int y_shift = yuv_type; | |
| 57 for (int y = 0; y < height; ++y) { | |
| 58 uint8* rgb_row = rgb_buf + y * rgb_pitch; | |
| 59 const uint8* y_ptr = y_buf + y * y_pitch; | |
| 60 const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch; | |
| 61 const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch; | |
| 62 | |
| 63 FastConvertYUVToRGB32Row(y_ptr, | |
| 64 u_ptr, | |
| 65 v_ptr, | |
| 66 rgb_row, | |
| 67 width); | |
| 68 } | |
| 69 | |
| 70 // MMX used for FastConvertYUVToRGB32Row requires emms instruction. | |
| 71 EMMS(); | |
| 72 } | |
| 73 | |
| 74 #if USE_SSE2 | |
| 75 // FilterRows combines two rows of the image using linear interpolation. | |
| 76 // SSE2 version does 16 pixels at a time | |
| 77 | |
| 78 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, | |
| 79 int source_width, int source_y_fraction) { | |
| 80 __m128i zero = _mm_setzero_si128(); | |
| 81 __m128i y1_fraction = _mm_set1_epi16(source_y_fraction); | |
| 82 __m128i y0_fraction = _mm_set1_epi16(256 - source_y_fraction); | |
| 83 | |
| 84 const __m128i* y0_ptr128 = reinterpret_cast<const __m128i*>(y0_ptr); | |
| 85 const __m128i* y1_ptr128 = reinterpret_cast<const __m128i*>(y1_ptr); | |
| 86 __m128i* dest128 = reinterpret_cast<__m128i*>(ybuf); | |
| 87 __m128i* end128 = reinterpret_cast<__m128i*>(ybuf + source_width); | |
| 88 | |
| 89 do { | |
| 90 __m128i y0 = _mm_loadu_si128(y0_ptr128); | |
| 91 __m128i y1 = _mm_loadu_si128(y1_ptr128); | |
| 92 __m128i y2 = _mm_unpackhi_epi8(y0, zero); | |
| 93 __m128i y3 = _mm_unpackhi_epi8(y1, zero); | |
| 94 y0 = _mm_unpacklo_epi8(y0, zero); | |
| 95 y1 = _mm_unpacklo_epi8(y1, zero); | |
| 96 y0 = _mm_mullo_epi16(y0, y0_fraction); | |
| 97 y1 = _mm_mullo_epi16(y1, y1_fraction); | |
| 98 y2 = _mm_mullo_epi16(y2, y0_fraction); | |
| 99 y3 = _mm_mullo_epi16(y3, y1_fraction); | |
| 100 y0 = _mm_add_epi16(y0, y1); | |
| 101 y2 = _mm_add_epi16(y2, y3); | |
| 102 y0 = _mm_srli_epi16(y0, 8); | |
| 103 y2 = _mm_srli_epi16(y2, 8); | |
| 104 y0 = _mm_packus_epi16(y0, y2); | |
| 105 *dest128++ = y0; | |
| 106 ++y0_ptr128; | |
| 107 ++y1_ptr128; | |
| 108 } while (dest128 < end128); | |
| 109 } | |
| 110 #elif USE_MMX | |
| 111 // MMX version does 8 pixels at a time | |
| 112 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, | |
| 113 int source_width, int source_y_fraction) { | |
| 114 __m64 zero = _mm_setzero_si64(); | |
| 115 __m64 y1_fraction = _mm_set1_pi16(source_y_fraction); | |
| 116 __m64 y0_fraction = _mm_set1_pi16(256 - source_y_fraction); | |
| 117 | |
| 118 const __m64* y0_ptr64 = reinterpret_cast<const __m64*>(y0_ptr); | |
| 119 const __m64* y1_ptr64 = reinterpret_cast<const __m64*>(y1_ptr); | |
| 120 __m64* dest64 = reinterpret_cast<__m64*>(ybuf); | |
| 121 __m64* end64 = reinterpret_cast<__m64*>(ybuf + source_width); | |
| 122 | |
| 123 do { | |
| 124 __m64 y0 = *y0_ptr64++; | |
| 125 __m64 y1 = *y1_ptr64++; | |
| 126 __m64 y2 = _mm_unpackhi_pi8(y0, zero); | |
| 127 __m64 y3 = _mm_unpackhi_pi8(y1, zero); | |
| 128 y0 = _mm_unpacklo_pi8(y0, zero); | |
| 129 y1 = _mm_unpacklo_pi8(y1, zero); | |
| 130 y0 = _mm_mullo_pi16(y0, y0_fraction); | |
| 131 y1 = _mm_mullo_pi16(y1, y1_fraction); | |
| 132 y2 = _mm_mullo_pi16(y2, y0_fraction); | |
| 133 y3 = _mm_mullo_pi16(y3, y1_fraction); | |
| 134 y0 = _mm_add_pi16(y0, y1); | |
| 135 y2 = _mm_add_pi16(y2, y3); | |
| 136 y0 = _mm_srli_pi16(y0, 8); | |
| 137 y2 = _mm_srli_pi16(y2, 8); | |
| 138 y0 = _mm_packs_pu16(y0, y2); | |
| 139 *dest64++ = y0; | |
| 140 } while (dest64 < end64); | |
| 141 } | |
| 142 #else // no MMX or SSE2 | |
| 143 // C version does 8 at a time to mimic MMX code | |
| 144 static void FilterRows(uint8* ybuf, const uint8* y0_ptr, const uint8* y1_ptr, | |
| 145 int source_width, int source_y_fraction) { | |
| 146 int y1_fraction = source_y_fraction; | |
| 147 int y0_fraction = 256 - y1_fraction; | |
| 148 uint8* end = ybuf + source_width; | |
| 149 do { | |
| 150 ybuf[0] = (y0_ptr[0] * y0_fraction + y1_ptr[0] * y1_fraction) >> 8; | |
| 151 ybuf[1] = (y0_ptr[1] * y0_fraction + y1_ptr[1] * y1_fraction) >> 8; | |
| 152 ybuf[2] = (y0_ptr[2] * y0_fraction + y1_ptr[2] * y1_fraction) >> 8; | |
| 153 ybuf[3] = (y0_ptr[3] * y0_fraction + y1_ptr[3] * y1_fraction) >> 8; | |
| 154 ybuf[4] = (y0_ptr[4] * y0_fraction + y1_ptr[4] * y1_fraction) >> 8; | |
| 155 ybuf[5] = (y0_ptr[5] * y0_fraction + y1_ptr[5] * y1_fraction) >> 8; | |
| 156 ybuf[6] = (y0_ptr[6] * y0_fraction + y1_ptr[6] * y1_fraction) >> 8; | |
| 157 ybuf[7] = (y0_ptr[7] * y0_fraction + y1_ptr[7] * y1_fraction) >> 8; | |
| 158 y0_ptr += 8; | |
| 159 y1_ptr += 8; | |
| 160 ybuf += 8; | |
| 161 } while (ybuf < end); | |
| 162 } | |
| 163 #endif | |
| 164 | |
| 165 | |
| 166 // Scale a frame of YUV to 32 bit ARGB. | 108 // Scale a frame of YUV to 32 bit ARGB. |
| 167 void ScaleYUVToRGB32(const uint8* y_buf, | 109 void ScaleYUVToRGB32(const uint8* y_buf, |
| 168 const uint8* u_buf, | 110 const uint8* u_buf, |
| 169 const uint8* v_buf, | 111 const uint8* v_buf, |
| 170 uint8* rgb_buf, | 112 uint8* rgb_buf, |
| 171 int source_width, | 113 int source_width, |
| 172 int source_height, | 114 int source_height, |
| 173 int width, | 115 int width, |
| 174 int height, | 116 int height, |
| 175 int y_pitch, | 117 int y_pitch, |
| 176 int uv_pitch, | 118 int uv_pitch, |
| 177 int rgb_pitch, | 119 int rgb_pitch, |
| 178 YUVType yuv_type, | 120 YUVType yuv_type, |
| 179 Rotate view_rotate, | 121 Rotate view_rotate, |
| 180 ScaleFilter filter) { | 122 ScaleFilter filter) { |
| 123 static FilterYUVRowsProc filter_proc = NULL; |
| 124 static ConvertYUVToRGB32RowProc convert_proc = NULL; |
| 125 static ScaleYUVToRGB32RowProc scale_proc = NULL; |
| 126 static ScaleYUVToRGB32RowProc linear_scale_proc = NULL; |
| 127 |
| 128 if (!filter_proc) |
| 129 filter_proc = ChooseFilterYUVRowsProc(); |
| 130 if (!convert_proc) |
| 131 convert_proc = ChooseConvertYUVToRGB32RowProc(); |
| 132 if (!scale_proc) |
| 133 scale_proc = ChooseScaleYUVToRGB32RowProc(); |
| 134 if (!linear_scale_proc) |
| 135 linear_scale_proc = ChooseLinearScaleYUVToRGB32RowProc(); |
| 136 |
| 181 // Handle zero sized sources and destinations. | 137 // Handle zero sized sources and destinations. |
| 182 if ((yuv_type == YV12 && (source_width < 2 || source_height < 2)) || | 138 if ((yuv_type == YV12 && (source_width < 2 || source_height < 2)) || |
| 183 (yuv_type == YV16 && (source_width < 2 || source_height < 1)) || | 139 (yuv_type == YV16 && (source_width < 2 || source_height < 1)) || |
| 184 width == 0 || height == 0) | 140 width == 0 || height == 0) |
| 185 return; | 141 return; |
| 186 | 142 |
| 187 // 4096 allows 3 buffers to fit in 12k. | 143 // 4096 allows 3 buffers to fit in 12k. |
| 188 // Helps performance on CPU with 16K L1 cache. | 144 // Helps performance on CPU with 16K L1 cache. |
| 189 // Large enough for 3830x2160 and 30" displays which are 2560x1600. | 145 // Large enough for 3830x2160 and 30" displays which are 2560x1600. |
| 190 const int kFilterBufferSize = 4096; | 146 const int kFilterBufferSize = 4096; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 218 (view_rotate == MIRROR_ROTATE_90) || | 174 (view_rotate == MIRROR_ROTATE_90) || |
| 219 (view_rotate == MIRROR_ROTATE_180)) { | 175 (view_rotate == MIRROR_ROTATE_180)) { |
| 220 y_buf += (source_height - 1) * y_pitch; | 176 y_buf += (source_height - 1) * y_pitch; |
| 221 u_buf += ((source_height >> y_shift) - 1) * uv_pitch; | 177 u_buf += ((source_height >> y_shift) - 1) * uv_pitch; |
| 222 v_buf += ((source_height >> y_shift) - 1) * uv_pitch; | 178 v_buf += ((source_height >> y_shift) - 1) * uv_pitch; |
| 223 source_height = -source_height; | 179 source_height = -source_height; |
| 224 } | 180 } |
| 225 | 181 |
| 226 int source_dx = source_width * kFractionMax / width; | 182 int source_dx = source_width * kFractionMax / width; |
| 227 int source_dy = source_height * kFractionMax / height; | 183 int source_dy = source_height * kFractionMax / height; |
| 228 #if USE_MMX && defined(_MSC_VER) | |
| 229 int source_dx_uv = source_dx; | |
| 230 #endif | |
| 231 | 184 |
| 232 if ((view_rotate == ROTATE_90) || | 185 if ((view_rotate == ROTATE_90) || |
| 233 (view_rotate == ROTATE_270)) { | 186 (view_rotate == ROTATE_270)) { |
| 234 int tmp = height; | 187 int tmp = height; |
| 235 height = width; | 188 height = width; |
| 236 width = tmp; | 189 width = tmp; |
| 237 tmp = source_height; | 190 tmp = source_height; |
| 238 source_height = source_width; | 191 source_height = source_width; |
| 239 source_width = tmp; | 192 source_width = tmp; |
| 240 int original_dx = source_dx; | 193 int original_dx = source_dx; |
| 241 int original_dy = source_dy; | 194 int original_dy = source_dy; |
| 242 source_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits; | 195 source_dx = ((original_dy >> kFractionBits) * y_pitch) << kFractionBits; |
| 243 #if USE_MMX && defined(_MSC_VER) | |
| 244 source_dx_uv = ((original_dy >> kFractionBits) * uv_pitch) << kFractionBits; | |
| 245 #endif | |
| 246 source_dy = original_dx; | 196 source_dy = original_dx; |
| 247 if (view_rotate == ROTATE_90) { | 197 if (view_rotate == ROTATE_90) { |
| 248 y_pitch = -1; | 198 y_pitch = -1; |
| 249 uv_pitch = -1; | 199 uv_pitch = -1; |
| 250 source_height = -source_height; | 200 source_height = -source_height; |
| 251 } else { | 201 } else { |
| 252 y_pitch = 1; | 202 y_pitch = 1; |
| 253 uv_pitch = 1; | 203 uv_pitch = 1; |
| 254 } | 204 } |
| 255 } | 205 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 ((source_y_subpixel >> y_shift) & kFractionMask) >> 8; | 237 ((source_y_subpixel >> y_shift) & kFractionMask) >> 8; |
| 288 | 238 |
| 289 const uint8* y_ptr = y0_ptr; | 239 const uint8* y_ptr = y0_ptr; |
| 290 const uint8* u_ptr = u0_ptr; | 240 const uint8* u_ptr = u0_ptr; |
| 291 const uint8* v_ptr = v0_ptr; | 241 const uint8* v_ptr = v0_ptr; |
| 292 // Apply vertical filtering if necessary. | 242 // Apply vertical filtering if necessary. |
| 293 // TODO(fbarchard): Remove memcpy when not necessary. | 243 // TODO(fbarchard): Remove memcpy when not necessary. |
| 294 if (filter & media::FILTER_BILINEAR_V) { | 244 if (filter & media::FILTER_BILINEAR_V) { |
| 295 if (yscale_fixed != kFractionMax && | 245 if (yscale_fixed != kFractionMax && |
| 296 source_y_fraction && ((source_y + 1) < source_height)) { | 246 source_y_fraction && ((source_y + 1) < source_height)) { |
| 297 FilterRows(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction); | 247 filter_proc(ybuf, y0_ptr, y1_ptr, source_width, source_y_fraction); |
| 298 } else { | 248 } else { |
| 299 memcpy(ybuf, y0_ptr, source_width); | 249 memcpy(ybuf, y0_ptr, source_width); |
| 300 } | 250 } |
| 301 y_ptr = ybuf; | 251 y_ptr = ybuf; |
| 302 ybuf[source_width] = ybuf[source_width-1]; | 252 ybuf[source_width] = ybuf[source_width-1]; |
| 303 int uv_source_width = (source_width + 1) / 2; | 253 int uv_source_width = (source_width + 1) / 2; |
| 304 if (yscale_fixed != kFractionMax && | 254 if (yscale_fixed != kFractionMax && |
| 305 source_uv_fraction && | 255 source_uv_fraction && |
| 306 (((source_y >> y_shift) + 1) < (source_height >> y_shift))) { | 256 (((source_y >> y_shift) + 1) < (source_height >> y_shift))) { |
| 307 FilterRows(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction); | 257 filter_proc(ubuf, u0_ptr, u1_ptr, uv_source_width, source_uv_fraction); |
| 308 FilterRows(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction); | 258 filter_proc(vbuf, v0_ptr, v1_ptr, uv_source_width, source_uv_fraction); |
| 309 } else { | 259 } else { |
| 310 memcpy(ubuf, u0_ptr, uv_source_width); | 260 memcpy(ubuf, u0_ptr, uv_source_width); |
| 311 memcpy(vbuf, v0_ptr, uv_source_width); | 261 memcpy(vbuf, v0_ptr, uv_source_width); |
| 312 } | 262 } |
| 313 u_ptr = ubuf; | 263 u_ptr = ubuf; |
| 314 v_ptr = vbuf; | 264 v_ptr = vbuf; |
| 315 ubuf[uv_source_width] = ubuf[uv_source_width - 1]; | 265 ubuf[uv_source_width] = ubuf[uv_source_width - 1]; |
| 316 vbuf[uv_source_width] = vbuf[uv_source_width - 1]; | 266 vbuf[uv_source_width] = vbuf[uv_source_width - 1]; |
| 317 } | 267 } |
| 318 if (source_dx == kFractionMax) { // Not scaled | 268 if (source_dx == kFractionMax) { // Not scaled |
| 319 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | 269 convert_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width); |
| 320 dest_pixel, width); | |
| 321 } else { | 270 } else { |
| 322 if (filter & FILTER_BILINEAR_H) { | 271 if (filter & FILTER_BILINEAR_H) { |
| 323 LinearScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | 272 linear_scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); |
| 324 dest_pixel, width, source_dx); | 273 } else { |
| 325 } else { | 274 scale_proc(y_ptr, u_ptr, v_ptr, dest_pixel, width, source_dx); |
| 326 // Specialized scalers and rotation. | |
| 327 #if USE_MMX && defined(_MSC_VER) | |
| 328 if (width == (source_width * 2)) { | |
| 329 DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | |
| 330 dest_pixel, width); | |
| 331 } else if ((source_dx & kFractionMask) == 0) { | |
| 332 // Scaling by integer scale factor. ie half. | |
| 333 ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | |
| 334 dest_pixel, width, | |
| 335 source_dx >> kFractionBits); | |
| 336 } else if (source_dx_uv == source_dx) { // Not rotated. | |
| 337 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | |
| 338 dest_pixel, width, source_dx); | |
| 339 } else { | |
| 340 RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | |
| 341 dest_pixel, width, | |
| 342 source_dx >> kFractionBits, | |
| 343 source_dx_uv >> kFractionBits); | |
| 344 } | |
| 345 #else | |
| 346 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, | |
| 347 dest_pixel, width, source_dx); | |
| 348 #endif | |
| 349 } | 275 } |
| 350 } | 276 } |
| 351 } | 277 } |
| 352 // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms. | 278 |
| 353 EMMS(); | 279 EmptyRegisterState(); |
| 354 } | 280 } |
| 355 | 281 |
| 356 void ConvertRGB32ToYUV(const uint8* rgbframe, | 282 void ConvertRGB32ToYUV(const uint8* rgbframe, |
| 357 uint8* yplane, | 283 uint8* yplane, |
| 358 uint8* uplane, | 284 uint8* uplane, |
| 359 uint8* vplane, | 285 uint8* vplane, |
| 360 int width, | 286 int width, |
| 361 int height, | 287 int height, |
| 362 int rgbstride, | 288 int rgbstride, |
| 363 int ystride, | 289 int ystride, |
| 364 int uvstride) { | 290 int uvstride) { |
| 365 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, | 291 static void (*convert_proc)(const uint8*, uint8*, uint8*, uint8*, |
| 366 int, int, int, int, int) = NULL; | 292 int, int, int, int, int) = NULL; |
| 367 if (!convert_proc) { | 293 if (!convert_proc) { |
| 368 #if defined(ARCH_CPU_ARM_FAMILY) | 294 #if defined(ARCH_CPU_ARM_FAMILY) |
| 369 // For ARM processors, always use C version. | 295 // For ARM processors, always use C version. |
| 370 // TODO(hclam): Implement a NEON version. | 296 // TODO(hclam): Implement a NEON version. |
| 371 convert_proc = &ConvertRGB32ToYUV_C; | 297 convert_proc = &ConvertRGB32ToYUV_C; |
| 372 #else | 298 #else |
| 373 // For x86 processors, check if SSSE3 (or SSE2) is supported. | |
| 374 if (hasSSE2()) | 299 if (hasSSE2()) |
| 375 convert_proc = &ConvertRGB32ToYUV_SSE2; | 300 convert_proc = &ConvertRGB32ToYUV_SSE2; |
| 376 else | 301 else |
| 377 convert_proc = &ConvertRGB32ToYUV_C; | 302 convert_proc = &ConvertRGB32ToYUV_C; |
| 378 #endif | 303 #endif |
| 379 } | 304 } |
| 380 | 305 |
| 381 convert_proc(rgbframe, yplane, uplane, vplane, width, height, | 306 convert_proc(rgbframe, yplane, uplane, vplane, width, height, |
| 382 rgbstride, ystride, uvstride); | 307 rgbstride, ystride, uvstride); |
| 383 } | 308 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 396 } | 321 } |
| 397 | 322 |
| 398 void ConvertYUY2ToYUV(const uint8* src, | 323 void ConvertYUY2ToYUV(const uint8* src, |
| 399 uint8* yplane, | 324 uint8* yplane, |
| 400 uint8* uplane, | 325 uint8* uplane, |
| 401 uint8* vplane, | 326 uint8* vplane, |
| 402 int width, | 327 int width, |
| 403 int height) { | 328 int height) { |
| 404 ConvertYUY2ToYUV_C(src, yplane, uplane, vplane, width, height); | 329 ConvertYUY2ToYUV_C(src, yplane, uplane, vplane, width, height); |
| 405 } | 330 } |
| 331 |
| 332 void ConvertYUVToRGB32(const uint8* yplane, |
| 333 const uint8* uplane, |
| 334 const uint8* vplane, |
| 335 uint8* rgbframe, |
| 336 int width, |
| 337 int height, |
| 338 int ystride, |
| 339 int uvstride, |
| 340 int rgbstride, |
| 341 YUVType yuv_type) { |
| 342 #if defined(ARCH_CPU_ARM_FAMILY) |
| 343 ConvertYUVToRGB32_C(yplane, uplane, vplane, rgbframe, |
| 344 width, height, ystride, uvstride, rgbstride, yuv_type); |
| 345 #else |
| 346 static ConvertYUVToRGB32Proc convert_proc = NULL; |
| 347 if (!convert_proc) { |
| 348 if (hasSSE()) |
| 349 convert_proc = &ConvertYUVToRGB32_SSE; |
| 350 else if (hasMMX()) |
| 351 convert_proc = &ConvertYUVToRGB32_MMX; |
| 352 else |
| 353 convert_proc = &ConvertYUVToRGB32_C; |
| 354 } |
| 355 |
| 356 convert_proc(yplane, uplane, vplane, rgbframe, |
| 357 width, height, ystride, uvstride, rgbstride, yuv_type); |
| 358 #endif |
| 359 } |
| 360 |
| 406 } // namespace media | 361 } // namespace media |
| OLD | NEW |