Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: media/base/yuv_convert.cc

Issue 7891039: Resubmit - Rewrite color space conversions suite using YASM" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/yuv_convert.h ('k') | media/base/yuv_convert_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698