2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "libyuv/row.h"
13 #include <string.h> // For memcpy and memset.
15 #include "libyuv/basic_types.h"
22 // llvm x86 is poor at ternary operator, so use branchless min/max.
24 #define USE_BRANCHLESS 1
26 static __inline int32 clamp0(int32 v) {
27 return ((-(v) >> 31) & (v));
30 static __inline int32 clamp255(int32 v) {
31 return (((255 - (v)) >> 31) | (v)) & 255;
34 static __inline uint32 Clamp(int32 val) {
36 return static_cast<uint32>(clamp255(v));
39 static __inline uint32 Abs(int32 v) {
43 #else // USE_BRANCHLESS
44 static __inline int32 clamp0(int32 v) {
45 return (v < 0) ? 0 : v;
48 static __inline int32 clamp255(int32 v) {
49 return (v > 255) ? 255 : v;
52 static __inline uint32 Clamp(int32 val) {
54 return static_cast<uint32>(clamp255(v));
57 static __inline uint32 Abs(int32 v) {
58 return (v < 0) ? -v : v;
60 #endif // USE_BRANCHLESS
62 #ifdef LIBYUV_LITTLE_ENDIAN
63 #define WRITEWORD(p, v) *reinterpret_cast<uint32*>(p) = v
65 static inline void WRITEWORD(uint8* p, uint32 v) {
66 p[0] = (uint8)(v & 255);
67 p[1] = (uint8)((v >> 8) & 255);
68 p[2] = (uint8)((v >> 16) & 255);
69 p[3] = (uint8)((v >> 24) & 255);
73 void RGB24ToARGBRow_C(const uint8* src_rgb24, uint8* dst_argb, int width) {
74 for (int x = 0; x < width; ++x) {
75 uint8 b = src_rgb24[0];
76 uint8 g = src_rgb24[1];
77 uint8 r = src_rgb24[2];
87 void RAWToARGBRow_C(const uint8* src_raw, uint8* dst_argb, int width) {
88 for (int x = 0; x < width; ++x) {
101 void RGB565ToARGBRow_C(const uint8* src_rgb565, uint8* dst_argb, int width) {
102 for (int x = 0; x < width; ++x) {
103 uint8 b = src_rgb565[0] & 0x1f;
104 uint8 g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3);
105 uint8 r = src_rgb565[1] >> 3;
106 dst_argb[0] = (b << 3) | (b >> 2);
107 dst_argb[1] = (g << 2) | (g >> 4);
108 dst_argb[2] = (r << 3) | (r >> 2);
115 void ARGB1555ToARGBRow_C(const uint8* src_argb1555, uint8* dst_argb,
117 for (int x = 0; x < width; ++x) {
118 uint8 b = src_argb1555[0] & 0x1f;
119 uint8 g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3);
120 uint8 r = (src_argb1555[1] & 0x7c) >> 2;
121 uint8 a = src_argb1555[1] >> 7;
122 dst_argb[0] = (b << 3) | (b >> 2);
123 dst_argb[1] = (g << 3) | (g >> 2);
124 dst_argb[2] = (r << 3) | (r >> 2);
131 void ARGB4444ToARGBRow_C(const uint8* src_argb4444, uint8* dst_argb,
133 for (int x = 0; x < width; ++x) {
134 uint8 b = src_argb4444[0] & 0x0f;
135 uint8 g = src_argb4444[0] >> 4;
136 uint8 r = src_argb4444[1] & 0x0f;
137 uint8 a = src_argb4444[1] >> 4;
138 dst_argb[0] = (b << 4) | b;
139 dst_argb[1] = (g << 4) | g;
140 dst_argb[2] = (r << 4) | r;
141 dst_argb[3] = (a << 4) | a;
147 void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
148 for (int x = 0; x < width; ++x) {
149 uint8 b = src_argb[0];
150 uint8 g = src_argb[1];
151 uint8 r = src_argb[2];
160 void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int width) {
161 for (int x = 0; x < width; ++x) {
162 uint8 b = src_argb[0];
163 uint8 g = src_argb[1];
164 uint8 r = src_argb[2];
173 void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
174 for (int x = 0; x < width - 1; x += 2) {
175 uint8 b0 = src_argb[0] >> 3;
176 uint8 g0 = src_argb[1] >> 2;
177 uint8 r0 = src_argb[2] >> 3;
178 uint8 b1 = src_argb[4] >> 3;
179 uint8 g1 = src_argb[5] >> 2;
180 uint8 r1 = src_argb[6] >> 3;
181 WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) |
182 (b1 << 16) | (g1 << 21) | (r1 << 27));
187 uint8 b0 = src_argb[0] >> 3;
188 uint8 g0 = src_argb[1] >> 2;
189 uint8 r0 = src_argb[2] >> 3;
190 *reinterpret_cast<uint16*>(dst_rgb) = b0 | (g0 << 5) | (r0 << 11);
194 void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
195 for (int x = 0; x < width - 1; x += 2) {
196 uint8 b0 = src_argb[0] >> 3;
197 uint8 g0 = src_argb[1] >> 3;
198 uint8 r0 = src_argb[2] >> 3;
199 uint8 a0 = src_argb[3] >> 7;
200 uint8 b1 = src_argb[4] >> 3;
201 uint8 g1 = src_argb[5] >> 3;
202 uint8 r1 = src_argb[6] >> 3;
203 uint8 a1 = src_argb[7] >> 7;
204 *reinterpret_cast<uint32*>(dst_rgb) =
205 b0 | (g0 << 5) | (r0 << 10) | (a0 << 15) |
206 (b1 << 16) | (g1 << 21) | (r1 << 26) | (a1 << 31);
211 uint8 b0 = src_argb[0] >> 3;
212 uint8 g0 = src_argb[1] >> 3;
213 uint8 r0 = src_argb[2] >> 3;
214 uint8 a0 = src_argb[3] >> 7;
215 *reinterpret_cast<uint16*>(dst_rgb) =
216 b0 | (g0 << 5) | (r0 << 10) | (a0 << 15);
220 void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
221 for (int x = 0; x < width - 1; x += 2) {
222 uint8 b0 = src_argb[0] >> 4;
223 uint8 g0 = src_argb[1] >> 4;
224 uint8 r0 = src_argb[2] >> 4;
225 uint8 a0 = src_argb[3] >> 4;
226 uint8 b1 = src_argb[4] >> 4;
227 uint8 g1 = src_argb[5] >> 4;
228 uint8 r1 = src_argb[6] >> 4;
229 uint8 a1 = src_argb[7] >> 4;
230 *reinterpret_cast<uint32*>(dst_rgb) =
231 b0 | (g0 << 4) | (r0 << 8) | (a0 << 12) |
232 (b1 << 16) | (g1 << 20) | (r1 << 24) | (a1 << 28);
237 uint8 b0 = src_argb[0] >> 4;
238 uint8 g0 = src_argb[1] >> 4;
239 uint8 r0 = src_argb[2] >> 4;
240 uint8 a0 = src_argb[3] >> 4;
241 *reinterpret_cast<uint16*>(dst_rgb) =
242 b0 | (g0 << 4) | (r0 << 8) | (a0 << 12);
246 static __inline int RGBToY(uint8 r, uint8 g, uint8 b) {
247 return (66 * r + 129 * g + 25 * b + 0x1080) >> 8;
250 static __inline int RGBToU(uint8 r, uint8 g, uint8 b) {
251 return (112 * b - 74 * g - 38 * r + 0x8080) >> 8;
253 static __inline int RGBToV(uint8 r, uint8 g, uint8 b) {
254 return (112 * r - 94 * g - 18 * b + 0x8080) >> 8;
257 #define MAKEROWY(NAME, R, G, B, BPP) \
258 void NAME ## ToYRow_C(const uint8* src_argb0, uint8* dst_y, int width) { \
259 for (int x = 0; x < width; ++x) { \
260 dst_y[0] = RGBToY(src_argb0[R], src_argb0[G], src_argb0[B]); \
265 void NAME ## ToUVRow_C(const uint8* src_rgb0, int src_stride_rgb, \
266 uint8* dst_u, uint8* dst_v, int width) { \
267 const uint8* src_rgb1 = src_rgb0 + src_stride_rgb; \
268 for (int x = 0; x < width - 1; x += 2) { \
269 uint8 ab = (src_rgb0[B] + src_rgb0[B + BPP] + \
270 src_rgb1[B] + src_rgb1[B + BPP]) >> 2; \
271 uint8 ag = (src_rgb0[G] + src_rgb0[G + BPP] + \
272 src_rgb1[G] + src_rgb1[G + BPP]) >> 2; \
273 uint8 ar = (src_rgb0[R] + src_rgb0[R + BPP] + \
274 src_rgb1[R] + src_rgb1[R + BPP]) >> 2; \
275 dst_u[0] = RGBToU(ar, ag, ab); \
276 dst_v[0] = RGBToV(ar, ag, ab); \
277 src_rgb0 += BPP * 2; \
278 src_rgb1 += BPP * 2; \
283 uint8 ab = (src_rgb0[B] + src_rgb1[B]) >> 1; \
284 uint8 ag = (src_rgb0[G] + src_rgb1[G]) >> 1; \
285 uint8 ar = (src_rgb0[R] + src_rgb1[R]) >> 1; \
286 dst_u[0] = RGBToU(ar, ag, ab); \
287 dst_v[0] = RGBToV(ar, ag, ab); \
291 MAKEROWY(ARGB, 2, 1, 0, 4)
292 MAKEROWY(BGRA, 1, 2, 3, 4)
293 MAKEROWY(ABGR, 0, 1, 2, 4)
294 MAKEROWY(RGBA, 3, 2, 1, 4)
295 MAKEROWY(RGB24, 2, 1, 0, 3)
296 MAKEROWY(RAW, 0, 1, 2, 3)
299 // JPeg uses a variation on BT.601-1 full range
300 // y = 0.29900 * r + 0.58700 * g + 0.11400 * b
301 // u = -0.16874 * r - 0.33126 * g + 0.50000 * b + center
302 // v = 0.50000 * r - 0.41869 * g - 0.08131 * b + center
303 // BT.601 Mpeg range uses:
304 // b 0.1016 * 255 = 25.908 = 25
305 // g 0.5078 * 255 = 129.489 = 129
306 // r 0.2578 * 255 = 65.739 = 66
307 // JPeg 8 bit Y (not used):
308 // b 0.11400 * 256 = 29.184 = 29
309 // g 0.58700 * 256 = 150.272 = 150
310 // r 0.29900 * 256 = 76.544 = 77
312 // b 0.11400 * 128 = 14.592 = 15
313 // g 0.58700 * 128 = 75.136 = 75
314 // r 0.29900 * 128 = 38.272 = 38
316 // b 0.50000 * 255 = 127.5 = 127
317 // g -0.33126 * 255 = -84.4713 = -84
318 // r -0.16874 * 255 = -43.0287 = -43
320 // b -0.08131 * 255 = -20.73405 = -20
321 // g -0.41869 * 255 = -106.76595 = -107
322 // r 0.50000 * 255 = 127.5 = 127
324 static __inline int RGBToYJ(uint8 r, uint8 g, uint8 b) {
325 return (38 * r + 75 * g + 15 * b + 64) >> 7;
328 static __inline int RGBToUJ(uint8 r, uint8 g, uint8 b) {
329 return (127 * b - 84 * g - 43 * r + 0x8080) >> 8;
331 static __inline int RGBToVJ(uint8 r, uint8 g, uint8 b) {
332 return (127 * r - 107 * g - 20 * b + 0x8080) >> 8;
335 #define AVGB(a, b) (((a) + (b) + 1) >> 1)
337 #define MAKEROWYJ(NAME, R, G, B, BPP) \
338 void NAME ## ToYJRow_C(const uint8* src_argb0, uint8* dst_y, int width) { \
339 for (int x = 0; x < width; ++x) { \
340 dst_y[0] = RGBToYJ(src_argb0[R], src_argb0[G], src_argb0[B]); \
345 void NAME ## ToUVJRow_C(const uint8* src_rgb0, int src_stride_rgb, \
346 uint8* dst_u, uint8* dst_v, int width) { \
347 const uint8* src_rgb1 = src_rgb0 + src_stride_rgb; \
348 for (int x = 0; x < width - 1; x += 2) { \
349 uint8 ab = AVGB(AVGB(src_rgb0[B], src_rgb1[B]), \
350 AVGB(src_rgb0[B + BPP], src_rgb1[B + BPP])); \
351 uint8 ag = AVGB(AVGB(src_rgb0[G], src_rgb1[G]), \
352 AVGB(src_rgb0[G + BPP], src_rgb1[G + BPP])); \
353 uint8 ar = AVGB(AVGB(src_rgb0[R], src_rgb1[R]), \
354 AVGB(src_rgb0[R + BPP], src_rgb1[R + BPP])); \
355 dst_u[0] = RGBToUJ(ar, ag, ab); \
356 dst_v[0] = RGBToVJ(ar, ag, ab); \
357 src_rgb0 += BPP * 2; \
358 src_rgb1 += BPP * 2; \
363 uint8 ab = AVGB(src_rgb0[B], src_rgb1[B]); \
364 uint8 ag = AVGB(src_rgb0[G], src_rgb1[G]); \
365 uint8 ar = AVGB(src_rgb0[R], src_rgb1[R]); \
366 dst_u[0] = RGBToUJ(ar, ag, ab); \
367 dst_v[0] = RGBToVJ(ar, ag, ab); \
371 MAKEROWYJ(ARGB, 2, 1, 0, 4)
374 void RGB565ToYRow_C(const uint8* src_rgb565, uint8* dst_y, int width) {
375 for (int x = 0; x < width; ++x) {
376 uint8 b = src_rgb565[0] & 0x1f;
377 uint8 g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3);
378 uint8 r = src_rgb565[1] >> 3;
379 b = (b << 3) | (b >> 2);
380 g = (g << 2) | (g >> 4);
381 r = (r << 3) | (r >> 2);
382 dst_y[0] = RGBToY(r, g, b);
388 void ARGB1555ToYRow_C(const uint8* src_argb1555, uint8* dst_y, int width) {
389 for (int x = 0; x < width; ++x) {
390 uint8 b = src_argb1555[0] & 0x1f;
391 uint8 g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3);
392 uint8 r = (src_argb1555[1] & 0x7c) >> 2;
393 b = (b << 3) | (b >> 2);
394 g = (g << 3) | (g >> 2);
395 r = (r << 3) | (r >> 2);
396 dst_y[0] = RGBToY(r, g, b);
402 void ARGB4444ToYRow_C(const uint8* src_argb4444, uint8* dst_y, int width) {
403 for (int x = 0; x < width; ++x) {
404 uint8 b = src_argb4444[0] & 0x0f;
405 uint8 g = src_argb4444[0] >> 4;
406 uint8 r = src_argb4444[1] & 0x0f;
410 dst_y[0] = RGBToY(r, g, b);
416 void RGB565ToUVRow_C(const uint8* src_rgb565, int src_stride_rgb565,
417 uint8* dst_u, uint8* dst_v, int width) {
418 const uint8* next_rgb565 = src_rgb565 + src_stride_rgb565;
419 for (int x = 0; x < width - 1; x += 2) {
420 uint8 b0 = src_rgb565[0] & 0x1f;
421 uint8 g0 = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3);
422 uint8 r0 = src_rgb565[1] >> 3;
423 uint8 b1 = src_rgb565[2] & 0x1f;
424 uint8 g1 = (src_rgb565[2] >> 5) | ((src_rgb565[3] & 0x07) << 3);
425 uint8 r1 = src_rgb565[3] >> 3;
426 uint8 b2 = next_rgb565[0] & 0x1f;
427 uint8 g2 = (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3);
428 uint8 r2 = next_rgb565[1] >> 3;
429 uint8 b3 = next_rgb565[2] & 0x1f;
430 uint8 g3 = (next_rgb565[2] >> 5) | ((next_rgb565[3] & 0x07) << 3);
431 uint8 r3 = next_rgb565[3] >> 3;
432 uint8 b = (b0 + b1 + b2 + b3); // 565 * 4 = 787.
433 uint8 g = (g0 + g1 + g2 + g3);
434 uint8 r = (r0 + r1 + r2 + r3);
435 b = (b << 1) | (b >> 6); // 787 -> 888.
436 r = (r << 1) | (r >> 6);
437 dst_u[0] = RGBToU(r, g, b);
438 dst_v[0] = RGBToV(r, g, b);
445 uint8 b0 = src_rgb565[0] & 0x1f;
446 uint8 g0 = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3);
447 uint8 r0 = src_rgb565[1] >> 3;
448 uint8 b2 = next_rgb565[0] & 0x1f;
449 uint8 g2 = (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3);
450 uint8 r2 = next_rgb565[1] >> 3;
451 uint8 b = (b0 + b2); // 565 * 2 = 676.
454 b = (b << 2) | (b >> 4); // 676 -> 888
455 g = (g << 1) | (g >> 6);
456 r = (r << 2) | (r >> 4);
457 dst_u[0] = RGBToU(r, g, b);
458 dst_v[0] = RGBToV(r, g, b);
462 void ARGB1555ToUVRow_C(const uint8* src_argb1555, int src_stride_argb1555,
463 uint8* dst_u, uint8* dst_v, int width) {
464 const uint8* next_argb1555 = src_argb1555 + src_stride_argb1555;
465 for (int x = 0; x < width - 1; x += 2) {
466 uint8 b0 = src_argb1555[0] & 0x1f;
467 uint8 g0 = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3);
468 uint8 r0 = (src_argb1555[1] & 0x7c) >> 2;
469 uint8 b1 = src_argb1555[2] & 0x1f;
470 uint8 g1 = (src_argb1555[2] >> 5) | ((src_argb1555[3] & 0x03) << 3);
471 uint8 r1 = (src_argb1555[3] & 0x7c) >> 2;
472 uint8 b2 = next_argb1555[0] & 0x1f;
473 uint8 g2 = (next_argb1555[0] >> 5) | ((next_argb1555[1] & 0x03) << 3);
474 uint8 r2 = (next_argb1555[1] & 0x7c) >> 2;
475 uint8 b3 = next_argb1555[2] & 0x1f;
476 uint8 g3 = (next_argb1555[2] >> 5) | ((next_argb1555[3] & 0x03) << 3);
477 uint8 r3 = (next_argb1555[3] & 0x7c) >> 2;
478 uint8 b = (b0 + b1 + b2 + b3); // 555 * 4 = 777.
479 uint8 g = (g0 + g1 + g2 + g3);
480 uint8 r = (r0 + r1 + r2 + r3);
481 b = (b << 1) | (b >> 6); // 777 -> 888.
482 g = (g << 1) | (g >> 6);
483 r = (r << 1) | (r >> 6);
484 dst_u[0] = RGBToU(r, g, b);
485 dst_v[0] = RGBToV(r, g, b);
492 uint8 b0 = src_argb1555[0] & 0x1f;
493 uint8 g0 = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3);
494 uint8 r0 = (src_argb1555[1] & 0x7c) >> 2;
495 uint8 b2 = next_argb1555[0] & 0x1f;
496 uint8 g2 = (next_argb1555[0] >> 5) | ((next_argb1555[1] & 0x03) << 3);
497 uint8 r2 = next_argb1555[1] >> 3;
498 uint8 b = (b0 + b2); // 555 * 2 = 666.
501 b = (b << 2) | (b >> 4); // 666 -> 888.
502 g = (g << 2) | (g >> 4);
503 r = (r << 2) | (r >> 4);
504 dst_u[0] = RGBToU(r, g, b);
505 dst_v[0] = RGBToV(r, g, b);
509 void ARGB4444ToUVRow_C(const uint8* src_argb4444, int src_stride_argb4444,
510 uint8* dst_u, uint8* dst_v, int width) {
511 const uint8* next_argb4444 = src_argb4444 + src_stride_argb4444;
512 for (int x = 0; x < width - 1; x += 2) {
513 uint8 b0 = src_argb4444[0] & 0x0f;
514 uint8 g0 = src_argb4444[0] >> 4;
515 uint8 r0 = src_argb4444[1] & 0x0f;
516 uint8 b1 = src_argb4444[2] & 0x0f;
517 uint8 g1 = src_argb4444[2] >> 4;
518 uint8 r1 = src_argb4444[3] & 0x0f;
519 uint8 b2 = next_argb4444[0] & 0x0f;
520 uint8 g2 = next_argb4444[0] >> 4;
521 uint8 r2 = next_argb4444[1] & 0x0f;
522 uint8 b3 = next_argb4444[2] & 0x0f;
523 uint8 g3 = next_argb4444[2] >> 4;
524 uint8 r3 = next_argb4444[3] & 0x0f;
525 uint8 b = (b0 + b1 + b2 + b3); // 444 * 4 = 666.
526 uint8 g = (g0 + g1 + g2 + g3);
527 uint8 r = (r0 + r1 + r2 + r3);
528 b = (b << 2) | (b >> 4); // 666 -> 888.
529 g = (g << 2) | (g >> 4);
530 r = (r << 2) | (r >> 4);
531 dst_u[0] = RGBToU(r, g, b);
532 dst_v[0] = RGBToV(r, g, b);
539 uint8 b0 = src_argb4444[0] & 0x0f;
540 uint8 g0 = src_argb4444[0] >> 4;
541 uint8 r0 = src_argb4444[1] & 0x0f;
542 uint8 b2 = next_argb4444[0] & 0x0f;
543 uint8 g2 = next_argb4444[0] >> 4;
544 uint8 r2 = next_argb4444[1] & 0x0f;
545 uint8 b = (b0 + b2); // 444 * 2 = 555.
548 b = (b << 3) | (b >> 2); // 555 -> 888.
549 g = (g << 3) | (g >> 2);
550 r = (r << 3) | (r >> 2);
551 dst_u[0] = RGBToU(r, g, b);
552 dst_v[0] = RGBToV(r, g, b);
556 void ARGBToUV444Row_C(const uint8* src_argb,
557 uint8* dst_u, uint8* dst_v, int width) {
558 for (int x = 0; x < width; ++x) {
559 uint8 ab = src_argb[0];
560 uint8 ag = src_argb[1];
561 uint8 ar = src_argb[2];
562 dst_u[0] = RGBToU(ar, ag, ab);
563 dst_v[0] = RGBToV(ar, ag, ab);
570 void ARGBToUV422Row_C(const uint8* src_argb,
571 uint8* dst_u, uint8* dst_v, int width) {
572 for (int x = 0; x < width - 1; x += 2) {
573 uint8 ab = (src_argb[0] + src_argb[4]) >> 1;
574 uint8 ag = (src_argb[1] + src_argb[5]) >> 1;
575 uint8 ar = (src_argb[2] + src_argb[6]) >> 1;
576 dst_u[0] = RGBToU(ar, ag, ab);
577 dst_v[0] = RGBToV(ar, ag, ab);
583 uint8 ab = src_argb[0];
584 uint8 ag = src_argb[1];
585 uint8 ar = src_argb[2];
586 dst_u[0] = RGBToU(ar, ag, ab);
587 dst_v[0] = RGBToV(ar, ag, ab);
591 void ARGBToUV411Row_C(const uint8* src_argb,
592 uint8* dst_u, uint8* dst_v, int width) {
593 for (int x = 0; x < width - 3; x += 4) {
594 uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8] + src_argb[12]) >> 2;
595 uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9] + src_argb[13]) >> 2;
596 uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10] + src_argb[14]) >> 2;
597 dst_u[0] = RGBToU(ar, ag, ab);
598 dst_v[0] = RGBToV(ar, ag, ab);
603 if ((width & 3) == 3) {
604 uint8 ab = (src_argb[0] + src_argb[4] + src_argb[8]) / 3;
605 uint8 ag = (src_argb[1] + src_argb[5] + src_argb[9]) / 3;
606 uint8 ar = (src_argb[2] + src_argb[6] + src_argb[10]) / 3;
607 dst_u[0] = RGBToU(ar, ag, ab);
608 dst_v[0] = RGBToV(ar, ag, ab);
609 } else if ((width & 3) == 2) {
610 uint8 ab = (src_argb[0] + src_argb[4]) >> 1;
611 uint8 ag = (src_argb[1] + src_argb[5]) >> 1;
612 uint8 ar = (src_argb[2] + src_argb[6]) >> 1;
613 dst_u[0] = RGBToU(ar, ag, ab);
614 dst_v[0] = RGBToV(ar, ag, ab);
615 } else if ((width & 3) == 1) {
616 uint8 ab = src_argb[0];
617 uint8 ag = src_argb[1];
618 uint8 ar = src_argb[2];
619 dst_u[0] = RGBToU(ar, ag, ab);
620 dst_v[0] = RGBToV(ar, ag, ab);
624 void ARGBGrayRow_C(const uint8* src_argb, uint8* dst_argb, int width) {
625 for (int x = 0; x < width; ++x) {
626 uint8 y = RGBToYJ(src_argb[2], src_argb[1], src_argb[0]);
627 dst_argb[2] = dst_argb[1] = dst_argb[0] = y;
628 dst_argb[3] = src_argb[3];
634 // Convert a row of image to Sepia tone.
635 void ARGBSepiaRow_C(uint8* dst_argb, int width) {
636 for (int x = 0; x < width; ++x) {
640 int sb = (b * 17 + g * 68 + r * 35) >> 7;
641 int sg = (b * 22 + g * 88 + r * 45) >> 7;
642 int sr = (b * 24 + g * 98 + r * 50) >> 7;
643 // b does not over flow. a is preserved from original.
645 dst_argb[1] = clamp255(sg);
646 dst_argb[2] = clamp255(sr);
651 // Apply color matrix to a row of image. Matrix is signed.
652 void ARGBColorMatrixRow_C(uint8* dst_argb, const int8* matrix_argb, int width) {
653 for (int x = 0; x < width; ++x) {
658 int sb = (b * matrix_argb[0] + g * matrix_argb[1] +
659 r * matrix_argb[2] + a * matrix_argb[3]) >> 7;
660 int sg = (b * matrix_argb[4] + g * matrix_argb[5] +
661 r * matrix_argb[6] + a * matrix_argb[7]) >> 7;
662 int sr = (b * matrix_argb[8] + g * matrix_argb[9] +
663 r * matrix_argb[10] + a * matrix_argb[11]) >> 7;
664 dst_argb[0] = Clamp(sb);
665 dst_argb[1] = Clamp(sg);
666 dst_argb[2] = Clamp(sr);
671 // Apply color table to a row of image.
672 void ARGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width) {
673 for (int x = 0; x < width; ++x) {
678 dst_argb[0] = table_argb[b * 4 + 0];
679 dst_argb[1] = table_argb[g * 4 + 1];
680 dst_argb[2] = table_argb[r * 4 + 2];
681 dst_argb[3] = table_argb[a * 4 + 3];
686 void ARGBQuantizeRow_C(uint8* dst_argb, int scale, int interval_size,
687 int interval_offset, int width) {
688 for (int x = 0; x < width; ++x) {
692 dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset;
693 dst_argb[1] = (g * scale >> 16) * interval_size + interval_offset;
694 dst_argb[2] = (r * scale >> 16) * interval_size + interval_offset;
699 #define REPEAT8(v) (v) | ((v) << 8)
700 #define SHADE(f, v) v * f >> 24
702 void ARGBShadeRow_C(const uint8* src_argb, uint8* dst_argb, int width,
704 const uint32 b_scale = REPEAT8(value & 0xff);
705 const uint32 g_scale = REPEAT8((value >> 8) & 0xff);
706 const uint32 r_scale = REPEAT8((value >> 16) & 0xff);
707 const uint32 a_scale = REPEAT8(value >> 24);
709 for (int i = 0; i < width; ++i) {
710 const uint32 b = REPEAT8(src_argb[0]);
711 const uint32 g = REPEAT8(src_argb[1]);
712 const uint32 r = REPEAT8(src_argb[2]);
713 const uint32 a = REPEAT8(src_argb[3]);
714 dst_argb[0] = SHADE(b, b_scale);
715 dst_argb[1] = SHADE(g, g_scale);
716 dst_argb[2] = SHADE(r, r_scale);
717 dst_argb[3] = SHADE(a, a_scale);
725 #define REPEAT8(v) (v) | ((v) << 8)
726 #define SHADE(f, v) v * f >> 16
728 void ARGBMultiplyRow_C(const uint8* src_argb0, const uint8* src_argb1,
729 uint8* dst_argb, int width) {
730 for (int i = 0; i < width; ++i) {
731 const uint32 b = REPEAT8(src_argb0[0]);
732 const uint32 g = REPEAT8(src_argb0[1]);
733 const uint32 r = REPEAT8(src_argb0[2]);
734 const uint32 a = REPEAT8(src_argb0[3]);
735 const uint32 b_scale = src_argb1[0];
736 const uint32 g_scale = src_argb1[1];
737 const uint32 r_scale = src_argb1[2];
738 const uint32 a_scale = src_argb1[3];
739 dst_argb[0] = SHADE(b, b_scale);
740 dst_argb[1] = SHADE(g, g_scale);
741 dst_argb[2] = SHADE(r, r_scale);
742 dst_argb[3] = SHADE(a, a_scale);
751 #define SHADE(f, v) clamp255(v + f)
753 void ARGBAddRow_C(const uint8* src_argb0, const uint8* src_argb1,
754 uint8* dst_argb, int width) {
755 for (int i = 0; i < width; ++i) {
756 const int b = src_argb0[0];
757 const int g = src_argb0[1];
758 const int r = src_argb0[2];
759 const int a = src_argb0[3];
760 const int b_add = src_argb1[0];
761 const int g_add = src_argb1[1];
762 const int r_add = src_argb1[2];
763 const int a_add = src_argb1[3];
764 dst_argb[0] = SHADE(b, b_add);
765 dst_argb[1] = SHADE(g, g_add);
766 dst_argb[2] = SHADE(r, r_add);
767 dst_argb[3] = SHADE(a, a_add);
775 #define SHADE(f, v) clamp0(f - v)
777 void ARGBSubtractRow_C(const uint8* src_argb0, const uint8* src_argb1,
778 uint8* dst_argb, int width) {
779 for (int i = 0; i < width; ++i) {
780 const int b = src_argb0[0];
781 const int g = src_argb0[1];
782 const int r = src_argb0[2];
783 const int a = src_argb0[3];
784 const int b_sub = src_argb1[0];
785 const int g_sub = src_argb1[1];
786 const int r_sub = src_argb1[2];
787 const int a_sub = src_argb1[3];
788 dst_argb[0] = SHADE(b, b_sub);
789 dst_argb[1] = SHADE(g, g_sub);
790 dst_argb[2] = SHADE(r, r_sub);
791 dst_argb[3] = SHADE(a, a_sub);
799 // Sobel functions which mimics SSSE3.
800 void SobelXRow_C(const uint8* src_y0, const uint8* src_y1, const uint8* src_y2,
801 uint8* dst_sobelx, int width) {
802 for (int i = 0; i < width; ++i) {
806 int a_sub = src_y0[i + 2];
807 int b_sub = src_y1[i + 2];
808 int c_sub = src_y2[i + 2];
809 int a_diff = a - a_sub;
810 int b_diff = b - b_sub;
811 int c_diff = c - c_sub;
812 int sobel = Abs(a_diff + b_diff * 2 + c_diff);
813 dst_sobelx[i] = static_cast<uint8>(clamp255(sobel));
817 void SobelYRow_C(const uint8* src_y0, const uint8* src_y1,
818 uint8* dst_sobely, int width) {
819 for (int i = 0; i < width; ++i) {
820 int a = src_y0[i + 0];
821 int b = src_y0[i + 1];
822 int c = src_y0[i + 2];
823 int a_sub = src_y1[i + 0];
824 int b_sub = src_y1[i + 1];
825 int c_sub = src_y1[i + 2];
826 int a_diff = a - a_sub;
827 int b_diff = b - b_sub;
828 int c_diff = c - c_sub;
829 int sobel = Abs(a_diff + b_diff * 2 + c_diff);
830 dst_sobely[i] = static_cast<uint8>(clamp255(sobel));
834 void SobelRow_C(const uint8* src_sobelx, const uint8* src_sobely,
835 uint8* dst_argb, int width) {
836 for (int i = 0; i < width; ++i) {
837 int r = src_sobelx[i];
838 int b = src_sobely[i];
839 int s = clamp255(r + b);
840 dst_argb[0] = static_cast<uint8>(s);
841 dst_argb[1] = static_cast<uint8>(s);
842 dst_argb[2] = static_cast<uint8>(s);
843 dst_argb[3] = static_cast<uint8>(255u);
848 void SobelXYRow_C(const uint8* src_sobelx, const uint8* src_sobely,
849 uint8* dst_argb, int width) {
850 for (int i = 0; i < width; ++i) {
851 int r = src_sobelx[i];
852 int b = src_sobely[i];
853 int g = clamp255(r + b);
854 dst_argb[0] = static_cast<uint8>(b);
855 dst_argb[1] = static_cast<uint8>(g);
856 dst_argb[2] = static_cast<uint8>(r);
857 dst_argb[3] = static_cast<uint8>(255u);
862 void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) {
864 for (int x = 0; x < width; ++x) {
866 dst_argb[2] = dst_argb[1] = dst_argb[0] = y;
873 // C reference code that mimics the YUV assembly.
875 #define YG 74 /* static_cast<int8>(1.164 * 64 + 0.5) */
877 #define UB 127 /* min(63,static_cast<int8>(2.018 * 64)) */
878 #define UG -25 /* static_cast<int8>(-0.391 * 64 - 0.5) */
882 #define VG -52 /* static_cast<int8>(-0.813 * 64 - 0.5) */
883 #define VR 102 /* static_cast<int8>(1.596 * 64 + 0.5) */
886 #define BB UB * 128 + VB * 128
887 #define BG UG * 128 + VG * 128
888 #define BR UR * 128 + VR * 128
890 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v,
891 uint8* b, uint8* g, uint8* r) {
892 int32 y1 = (static_cast<int32>(y) - 16) * YG;
893 *b = Clamp(static_cast<int32>((u * UB + v * VB) - (BB) + y1) >> 6);
894 *g = Clamp(static_cast<int32>((u * UG + v * VG) - (BG) + y1) >> 6);
895 *r = Clamp(static_cast<int32>((u * UR + v * VR) - (BR) + y1) >> 6);
898 #if !defined(LIBYUV_DISABLE_NEON) && \
899 (defined(__ARM_NEON__) || defined(LIBYUV_NEON))
901 // TODO(fbarchard): Remove subsampling from Neon.
902 void I444ToARGBRow_C(const uint8* src_y,
907 for (int x = 0; x < width - 1; x += 2) {
908 uint8 u = (src_u[0] + src_u[1] + 1) >> 1;
909 uint8 v = (src_v[0] + src_v[1] + 1) >> 1;
910 YuvPixel(src_y[0], u, v, rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
912 YuvPixel(src_y[1], u, v, rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
917 rgb_buf += 8; // Advance 2 pixels.
920 YuvPixel(src_y[0], src_u[0], src_v[0],
921 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
925 void I444ToARGBRow_C(const uint8* src_y,
930 for (int x = 0; x < width; ++x) {
931 YuvPixel(src_y[0], src_u[0], src_v[0],
932 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
937 rgb_buf += 4; // Advance 1 pixel.
942 void I422ToARGBRow_C(const uint8* src_y,
947 for (int x = 0; x < width - 1; x += 2) {
948 YuvPixel(src_y[0], src_u[0], src_v[0],
949 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
951 YuvPixel(src_y[1], src_u[0], src_v[0],
952 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
957 rgb_buf += 8; // Advance 2 pixels.
960 YuvPixel(src_y[0], src_u[0], src_v[0],
961 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
966 void I422ToRGB24Row_C(const uint8* src_y,
971 for (int x = 0; x < width - 1; x += 2) {
972 YuvPixel(src_y[0], src_u[0], src_v[0],
973 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
974 YuvPixel(src_y[1], src_u[0], src_v[0],
975 rgb_buf + 3, rgb_buf + 4, rgb_buf + 5);
979 rgb_buf += 6; // Advance 2 pixels.
982 YuvPixel(src_y[0], src_u[0], src_v[0],
983 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
987 void I422ToRAWRow_C(const uint8* src_y,
992 for (int x = 0; x < width - 1; x += 2) {
993 YuvPixel(src_y[0], src_u[0], src_v[0],
994 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
995 YuvPixel(src_y[1], src_u[0], src_v[0],
996 rgb_buf + 5, rgb_buf + 4, rgb_buf + 3);
1000 rgb_buf += 6; // Advance 2 pixels.
1003 YuvPixel(src_y[0], src_u[0], src_v[0],
1004 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
1008 void I422ToARGB4444Row_C(const uint8* src_y,
1011 uint8* dst_argb4444,
1019 for (int x = 0; x < width - 1; x += 2) {
1020 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1021 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1);
1028 *reinterpret_cast<uint32*>(dst_argb4444) = b0 | (g0 << 4) | (r0 << 8) |
1029 (b1 << 16) | (g1 << 20) | (r1 << 24) | 0xf000f000;
1033 dst_argb4444 += 4; // Advance 2 pixels.
1036 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1040 *reinterpret_cast<uint16*>(dst_argb4444) = b0 | (g0 << 4) | (r0 << 8) |
1045 void I422ToARGB1555Row_C(const uint8* src_y,
1048 uint8* dst_argb1555,
1056 for (int x = 0; x < width - 1; x += 2) {
1057 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1058 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1);
1065 *reinterpret_cast<uint32*>(dst_argb1555) = b0 | (g0 << 5) | (r0 << 10) |
1066 (b1 << 16) | (g1 << 21) | (r1 << 26) | 0x80008000;
1070 dst_argb1555 += 4; // Advance 2 pixels.
1073 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1077 *reinterpret_cast<uint16*>(dst_argb1555) = b0 | (g0 << 5) | (r0 << 10) |
1082 void I422ToRGB565Row_C(const uint8* src_y,
1093 for (int x = 0; x < width - 1; x += 2) {
1094 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1095 YuvPixel(src_y[1], src_u[0], src_v[0], &b1, &g1, &r1);
1102 *reinterpret_cast<uint32*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) |
1103 (b1 << 16) | (g1 << 21) | (r1 << 27);
1107 dst_rgb565 += 4; // Advance 2 pixels.
1110 YuvPixel(src_y[0], src_u[0], src_v[0], &b0, &g0, &r0);
1114 *reinterpret_cast<uint16*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11);
1118 void I411ToARGBRow_C(const uint8* src_y,
1123 for (int x = 0; x < width - 3; x += 4) {
1124 YuvPixel(src_y[0], src_u[0], src_v[0],
1125 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1127 YuvPixel(src_y[1], src_u[0], src_v[0],
1128 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1130 YuvPixel(src_y[2], src_u[0], src_v[0],
1131 rgb_buf + 8, rgb_buf + 9, rgb_buf + 10);
1133 YuvPixel(src_y[3], src_u[0], src_v[0],
1134 rgb_buf + 12, rgb_buf + 13, rgb_buf + 14);
1139 rgb_buf += 16; // Advance 4 pixels.
1142 YuvPixel(src_y[0], src_u[0], src_v[0],
1143 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1145 YuvPixel(src_y[1], src_u[0], src_v[0],
1146 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1149 rgb_buf += 8; // Advance 2 pixels.
1152 YuvPixel(src_y[0], src_u[0], src_v[0],
1153 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1158 void NV12ToARGBRow_C(const uint8* src_y,
1159 const uint8* usrc_v,
1162 for (int x = 0; x < width - 1; x += 2) {
1163 YuvPixel(src_y[0], usrc_v[0], usrc_v[1],
1164 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1166 YuvPixel(src_y[1], usrc_v[0], usrc_v[1],
1167 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1171 rgb_buf += 8; // Advance 2 pixels.
1174 YuvPixel(src_y[0], usrc_v[0], usrc_v[1],
1175 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1180 void NV21ToARGBRow_C(const uint8* src_y,
1181 const uint8* src_vu,
1184 for (int x = 0; x < width - 1; x += 2) {
1185 YuvPixel(src_y[0], src_vu[1], src_vu[0],
1186 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1189 YuvPixel(src_y[1], src_vu[1], src_vu[0],
1190 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1195 rgb_buf += 8; // Advance 2 pixels.
1198 YuvPixel(src_y[0], src_vu[1], src_vu[0],
1199 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1204 void NV12ToRGB565Row_C(const uint8* src_y,
1205 const uint8* usrc_v,
1214 for (int x = 0; x < width - 1; x += 2) {
1215 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0);
1216 YuvPixel(src_y[1], usrc_v[0], usrc_v[1], &b1, &g1, &r1);
1223 *reinterpret_cast<uint32*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) |
1224 (b1 << 16) | (g1 << 21) | (r1 << 27);
1227 dst_rgb565 += 4; // Advance 2 pixels.
1230 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0);
1234 *reinterpret_cast<uint16*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11);
1238 void NV21ToRGB565Row_C(const uint8* src_y,
1239 const uint8* vsrc_u,
1248 for (int x = 0; x < width - 1; x += 2) {
1249 YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0);
1250 YuvPixel(src_y[1], vsrc_u[1], vsrc_u[0], &b1, &g1, &r1);
1257 *reinterpret_cast<uint32*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) |
1258 (b1 << 16) | (g1 << 21) | (r1 << 27);
1261 dst_rgb565 += 4; // Advance 2 pixels.
1264 YuvPixel(src_y[0], vsrc_u[1], vsrc_u[0], &b0, &g0, &r0);
1268 *reinterpret_cast<uint16*>(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11);
1272 void YUY2ToARGBRow_C(const uint8* src_yuy2,
1275 for (int x = 0; x < width - 1; x += 2) {
1276 YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3],
1277 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1279 YuvPixel(src_yuy2[2], src_yuy2[1], src_yuy2[3],
1280 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1283 rgb_buf += 8; // Advance 2 pixels.
1286 YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3],
1287 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1292 void UYVYToARGBRow_C(const uint8* src_uyvy,
1295 for (int x = 0; x < width - 1; x += 2) {
1296 YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2],
1297 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1299 YuvPixel(src_uyvy[3], src_uyvy[0], src_uyvy[2],
1300 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1303 rgb_buf += 8; // Advance 2 pixels.
1306 YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2],
1307 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1312 void I422ToBGRARow_C(const uint8* src_y,
1317 for (int x = 0; x < width - 1; x += 2) {
1318 YuvPixel(src_y[0], src_u[0], src_v[0],
1319 rgb_buf + 3, rgb_buf + 2, rgb_buf + 1);
1321 YuvPixel(src_y[1], src_u[0], src_v[0],
1322 rgb_buf + 7, rgb_buf + 6, rgb_buf + 5);
1327 rgb_buf += 8; // Advance 2 pixels.
1330 YuvPixel(src_y[0], src_u[0], src_v[0],
1331 rgb_buf + 3, rgb_buf + 2, rgb_buf + 1);
1336 void I422ToABGRRow_C(const uint8* src_y,
1341 for (int x = 0; x < width - 1; x += 2) {
1342 YuvPixel(src_y[0], src_u[0], src_v[0],
1343 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
1345 YuvPixel(src_y[1], src_u[0], src_v[0],
1346 rgb_buf + 6, rgb_buf + 5, rgb_buf + 4);
1351 rgb_buf += 8; // Advance 2 pixels.
1354 YuvPixel(src_y[0], src_u[0], src_v[0],
1355 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0);
1360 void I422ToRGBARow_C(const uint8* src_y,
1365 for (int x = 0; x < width - 1; x += 2) {
1366 YuvPixel(src_y[0], src_u[0], src_v[0],
1367 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3);
1369 YuvPixel(src_y[1], src_u[0], src_v[0],
1370 rgb_buf + 5, rgb_buf + 6, rgb_buf + 7);
1375 rgb_buf += 8; // Advance 2 pixels.
1378 YuvPixel(src_y[0], src_u[0], src_v[0],
1379 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3);
1384 void YToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) {
1385 for (int x = 0; x < width - 1; x += 2) {
1386 YuvPixel(src_y[0], 128, 128,
1387 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1389 YuvPixel(src_y[1], 128, 128,
1390 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6);
1393 rgb_buf += 8; // Advance 2 pixels.
1396 YuvPixel(src_y[0], 128, 128,
1397 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2);
1402 void MirrorRow_C(const uint8* src, uint8* dst, int width) {
1404 for (int x = 0; x < width - 1; x += 2) {
1406 dst[x + 1] = src[-1];
1410 dst[width - 1] = src[0];
1414 void MirrorUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) {
1415 src_uv += (width - 1) << 1;
1416 for (int x = 0; x < width - 1; x += 2) {
1417 dst_u[x] = src_uv[0];
1418 dst_u[x + 1] = src_uv[-2];
1419 dst_v[x] = src_uv[1];
1420 dst_v[x + 1] = src_uv[-2 + 1];
1424 dst_u[width - 1] = src_uv[0];
1425 dst_v[width - 1] = src_uv[1];
1429 void ARGBMirrorRow_C(const uint8* src, uint8* dst, int width) {
1430 const uint32* src32 = reinterpret_cast<const uint32*>(src);
1431 uint32* dst32 = reinterpret_cast<uint32*>(dst);
1433 for (int x = 0; x < width - 1; x += 2) {
1434 dst32[x] = src32[0];
1435 dst32[x + 1] = src32[-1];
1439 dst32[width - 1] = src32[0];
1443 void SplitUVRow_C(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int width) {
1444 for (int x = 0; x < width - 1; x += 2) {
1445 dst_u[x] = src_uv[0];
1446 dst_u[x + 1] = src_uv[2];
1447 dst_v[x] = src_uv[1];
1448 dst_v[x + 1] = src_uv[3];
1452 dst_u[width - 1] = src_uv[0];
1453 dst_v[width - 1] = src_uv[1];
1457 void MergeUVRow_C(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
1459 for (int x = 0; x < width - 1; x += 2) {
1460 dst_uv[0] = src_u[x];
1461 dst_uv[1] = src_v[x];
1462 dst_uv[2] = src_u[x + 1];
1463 dst_uv[3] = src_v[x + 1];
1467 dst_uv[0] = src_u[width - 1];
1468 dst_uv[1] = src_v[width - 1];
1472 void CopyRow_C(const uint8* src, uint8* dst, int count) {
1473 memcpy(dst, src, count);
1476 void SetRow_C(uint8* dst, uint32 v8, int count) {
1478 // VC will generate rep stosb.
1479 for (int x = 0; x < count; ++x) {
1483 memset(dst, v8, count);
1487 void ARGBSetRows_C(uint8* dst, uint32 v32, int width,
1488 int dst_stride, int height) {
1489 for (int y = 0; y < height; ++y) {
1490 uint32* d = reinterpret_cast<uint32*>(dst);
1491 for (int x = 0; x < width; ++x) {
1498 // Filter 2 rows of YUY2 UV's (422) into U and V (420).
1499 void YUY2ToUVRow_C(const uint8* src_yuy2, int src_stride_yuy2,
1500 uint8* dst_u, uint8* dst_v, int width) {
1501 // Output a row of UV values, filtering 2 rows of YUY2.
1502 for (int x = 0; x < width; x += 2) {
1503 dst_u[0] = (src_yuy2[1] + src_yuy2[src_stride_yuy2 + 1] + 1) >> 1;
1504 dst_v[0] = (src_yuy2[3] + src_yuy2[src_stride_yuy2 + 3] + 1) >> 1;
1511 // Copy row of YUY2 UV's (422) into U and V (422).
1512 void YUY2ToUV422Row_C(const uint8* src_yuy2,
1513 uint8* dst_u, uint8* dst_v, int width) {
1514 // Output a row of UV values.
1515 for (int x = 0; x < width; x += 2) {
1516 dst_u[0] = src_yuy2[1];
1517 dst_v[0] = src_yuy2[3];
1524 // Copy row of YUY2 Y's (422) into Y (420/422).
1525 void YUY2ToYRow_C(const uint8* src_yuy2, uint8* dst_y, int width) {
1526 // Output a row of Y values.
1527 for (int x = 0; x < width - 1; x += 2) {
1528 dst_y[x] = src_yuy2[0];
1529 dst_y[x + 1] = src_yuy2[2];
1533 dst_y[width - 1] = src_yuy2[0];
1537 // Filter 2 rows of UYVY UV's (422) into U and V (420).
1538 void UYVYToUVRow_C(const uint8* src_uyvy, int src_stride_uyvy,
1539 uint8* dst_u, uint8* dst_v, int width) {
1540 // Output a row of UV values.
1541 for (int x = 0; x < width; x += 2) {
1542 dst_u[0] = (src_uyvy[0] + src_uyvy[src_stride_uyvy + 0] + 1) >> 1;
1543 dst_v[0] = (src_uyvy[2] + src_uyvy[src_stride_uyvy + 2] + 1) >> 1;
1550 // Copy row of UYVY UV's (422) into U and V (422).
1551 void UYVYToUV422Row_C(const uint8* src_uyvy,
1552 uint8* dst_u, uint8* dst_v, int width) {
1553 // Output a row of UV values.
1554 for (int x = 0; x < width; x += 2) {
1555 dst_u[0] = src_uyvy[0];
1556 dst_v[0] = src_uyvy[2];
1563 // Copy row of UYVY Y's (422) into Y (420/422).
1564 void UYVYToYRow_C(const uint8* src_uyvy, uint8* dst_y, int width) {
1565 // Output a row of Y values.
1566 for (int x = 0; x < width - 1; x += 2) {
1567 dst_y[x] = src_uyvy[1];
1568 dst_y[x + 1] = src_uyvy[3];
1572 dst_y[width - 1] = src_uyvy[1];
1576 #define BLEND(f, b, a) (((256 - a) * b) >> 8) + f
1578 // Blend src_argb0 over src_argb1 and store to dst_argb.
1579 // dst_argb may be src_argb0 or src_argb1.
1580 // This code mimics the SSSE3 version for better testability.
1581 void ARGBBlendRow_C(const uint8* src_argb0, const uint8* src_argb1,
1582 uint8* dst_argb, int width) {
1583 for (int x = 0; x < width - 1; x += 2) {
1584 uint32 fb = src_argb0[0];
1585 uint32 fg = src_argb0[1];
1586 uint32 fr = src_argb0[2];
1587 uint32 a = src_argb0[3];
1588 uint32 bb = src_argb1[0];
1589 uint32 bg = src_argb1[1];
1590 uint32 br = src_argb1[2];
1591 dst_argb[0] = BLEND(fb, bb, a);
1592 dst_argb[1] = BLEND(fg, bg, a);
1593 dst_argb[2] = BLEND(fr, br, a);
1596 fb = src_argb0[4 + 0];
1597 fg = src_argb0[4 + 1];
1598 fr = src_argb0[4 + 2];
1599 a = src_argb0[4 + 3];
1600 bb = src_argb1[4 + 0];
1601 bg = src_argb1[4 + 1];
1602 br = src_argb1[4 + 2];
1603 dst_argb[4 + 0] = BLEND(fb, bb, a);
1604 dst_argb[4 + 1] = BLEND(fg, bg, a);
1605 dst_argb[4 + 2] = BLEND(fr, br, a);
1606 dst_argb[4 + 3] = 255u;
1613 uint32 fb = src_argb0[0];
1614 uint32 fg = src_argb0[1];
1615 uint32 fr = src_argb0[2];
1616 uint32 a = src_argb0[3];
1617 uint32 bb = src_argb1[0];
1618 uint32 bg = src_argb1[1];
1619 uint32 br = src_argb1[2];
1620 dst_argb[0] = BLEND(fb, bb, a);
1621 dst_argb[1] = BLEND(fg, bg, a);
1622 dst_argb[2] = BLEND(fr, br, a);
1627 #define ATTENUATE(f, a) (a | (a << 8)) * (f | (f << 8)) >> 24
1629 // Multiply source RGB by alpha and store to destination.
1630 // This code mimics the SSSE3 version for better testability.
1631 void ARGBAttenuateRow_C(const uint8* src_argb, uint8* dst_argb, int width) {
1632 for (int i = 0; i < width - 1; i += 2) {
1633 uint32 b = src_argb[0];
1634 uint32 g = src_argb[1];
1635 uint32 r = src_argb[2];
1636 uint32 a = src_argb[3];
1637 dst_argb[0] = ATTENUATE(b, a);
1638 dst_argb[1] = ATTENUATE(g, a);
1639 dst_argb[2] = ATTENUATE(r, a);
1645 dst_argb[4] = ATTENUATE(b, a);
1646 dst_argb[5] = ATTENUATE(g, a);
1647 dst_argb[6] = ATTENUATE(r, a);
1654 const uint32 b = src_argb[0];
1655 const uint32 g = src_argb[1];
1656 const uint32 r = src_argb[2];
1657 const uint32 a = src_argb[3];
1658 dst_argb[0] = ATTENUATE(b, a);
1659 dst_argb[1] = ATTENUATE(g, a);
1660 dst_argb[2] = ATTENUATE(r, a);
1666 // Divide source RGB by alpha and store to destination.
1667 // b = (b * 255 + (a / 2)) / a;
1668 // g = (g * 255 + (a / 2)) / a;
1669 // r = (r * 255 + (a / 2)) / a;
1670 // Reciprocal method is off by 1 on some values. ie 125
1671 // 8.8 fixed point inverse table with 1.0 in upper short and 1 / a in lower.
1672 #define T(a) 0x01000000 + (0x10000 / a)
1673 uint32 fixed_invtbl8[256] = {
1674 0x01000000, 0x0100ffff, T(0x02), T(0x03), T(0x04), T(0x05), T(0x06), T(0x07),
1675 T(0x08), T(0x09), T(0x0a), T(0x0b), T(0x0c), T(0x0d), T(0x0e), T(0x0f),
1676 T(0x10), T(0x11), T(0x12), T(0x13), T(0x14), T(0x15), T(0x16), T(0x17),
1677 T(0x18), T(0x19), T(0x1a), T(0x1b), T(0x1c), T(0x1d), T(0x1e), T(0x1f),
1678 T(0x20), T(0x21), T(0x22), T(0x23), T(0x24), T(0x25), T(0x26), T(0x27),
1679 T(0x28), T(0x29), T(0x2a), T(0x2b), T(0x2c), T(0x2d), T(0x2e), T(0x2f),
1680 T(0x30), T(0x31), T(0x32), T(0x33), T(0x34), T(0x35), T(0x36), T(0x37),
1681 T(0x38), T(0x39), T(0x3a), T(0x3b), T(0x3c), T(0x3d), T(0x3e), T(0x3f),
1682 T(0x40), T(0x41), T(0x42), T(0x43), T(0x44), T(0x45), T(0x46), T(0x47),
1683 T(0x48), T(0x49), T(0x4a), T(0x4b), T(0x4c), T(0x4d), T(0x4e), T(0x4f),
1684 T(0x50), T(0x51), T(0x52), T(0x53), T(0x54), T(0x55), T(0x56), T(0x57),
1685 T(0x58), T(0x59), T(0x5a), T(0x5b), T(0x5c), T(0x5d), T(0x5e), T(0x5f),
1686 T(0x60), T(0x61), T(0x62), T(0x63), T(0x64), T(0x65), T(0x66), T(0x67),
1687 T(0x68), T(0x69), T(0x6a), T(0x6b), T(0x6c), T(0x6d), T(0x6e), T(0x6f),
1688 T(0x70), T(0x71), T(0x72), T(0x73), T(0x74), T(0x75), T(0x76), T(0x77),
1689 T(0x78), T(0x79), T(0x7a), T(0x7b), T(0x7c), T(0x7d), T(0x7e), T(0x7f),
1690 T(0x80), T(0x81), T(0x82), T(0x83), T(0x84), T(0x85), T(0x86), T(0x87),
1691 T(0x88), T(0x89), T(0x8a), T(0x8b), T(0x8c), T(0x8d), T(0x8e), T(0x8f),
1692 T(0x90), T(0x91), T(0x92), T(0x93), T(0x94), T(0x95), T(0x96), T(0x97),
1693 T(0x98), T(0x99), T(0x9a), T(0x9b), T(0x9c), T(0x9d), T(0x9e), T(0x9f),
1694 T(0xa0), T(0xa1), T(0xa2), T(0xa3), T(0xa4), T(0xa5), T(0xa6), T(0xa7),
1695 T(0xa8), T(0xa9), T(0xaa), T(0xab), T(0xac), T(0xad), T(0xae), T(0xaf),
1696 T(0xb0), T(0xb1), T(0xb2), T(0xb3), T(0xb4), T(0xb5), T(0xb6), T(0xb7),
1697 T(0xb8), T(0xb9), T(0xba), T(0xbb), T(0xbc), T(0xbd), T(0xbe), T(0xbf),
1698 T(0xc0), T(0xc1), T(0xc2), T(0xc3), T(0xc4), T(0xc5), T(0xc6), T(0xc7),
1699 T(0xc8), T(0xc9), T(0xca), T(0xcb), T(0xcc), T(0xcd), T(0xce), T(0xcf),
1700 T(0xd0), T(0xd1), T(0xd2), T(0xd3), T(0xd4), T(0xd5), T(0xd6), T(0xd7),
1701 T(0xd8), T(0xd9), T(0xda), T(0xdb), T(0xdc), T(0xdd), T(0xde), T(0xdf),
1702 T(0xe0), T(0xe1), T(0xe2), T(0xe3), T(0xe4), T(0xe5), T(0xe6), T(0xe7),
1703 T(0xe8), T(0xe9), T(0xea), T(0xeb), T(0xec), T(0xed), T(0xee), T(0xef),
1704 T(0xf0), T(0xf1), T(0xf2), T(0xf3), T(0xf4), T(0xf5), T(0xf6), T(0xf7),
1705 T(0xf8), T(0xf9), T(0xfa), T(0xfb), T(0xfc), T(0xfd), T(0xfe), 0x01000100 };
1708 void ARGBUnattenuateRow_C(const uint8* src_argb, uint8* dst_argb, int width) {
1709 for (int i = 0; i < width; ++i) {
1710 uint32 b = src_argb[0];
1711 uint32 g = src_argb[1];
1712 uint32 r = src_argb[2];
1713 const uint32 a = src_argb[3];
1714 const uint32 ia = fixed_invtbl8[a] & 0xffff; // 8.8 fixed point
1718 // Clamping should not be necessary but is free in assembly.
1719 dst_argb[0] = clamp255(b);
1720 dst_argb[1] = clamp255(g);
1721 dst_argb[2] = clamp255(r);
1728 void ComputeCumulativeSumRow_C(const uint8* row, int32* cumsum,
1729 const int32* previous_cumsum, int width) {
1730 int32 row_sum[4] = {0, 0, 0, 0};
1731 for (int x = 0; x < width; ++x) {
1732 row_sum[0] += row[x * 4 + 0];
1733 row_sum[1] += row[x * 4 + 1];
1734 row_sum[2] += row[x * 4 + 2];
1735 row_sum[3] += row[x * 4 + 3];
1736 cumsum[x * 4 + 0] = row_sum[0] + previous_cumsum[x * 4 + 0];
1737 cumsum[x * 4 + 1] = row_sum[1] + previous_cumsum[x * 4 + 1];
1738 cumsum[x * 4 + 2] = row_sum[2] + previous_cumsum[x * 4 + 2];
1739 cumsum[x * 4 + 3] = row_sum[3] + previous_cumsum[x * 4 + 3];
1743 void CumulativeSumToAverageRow_C(const int32* tl, const int32* bl,
1744 int w, int area, uint8* dst, int count) {
1745 float ooa = 1.0f / area;
1746 for (int i = 0; i < count; ++i) {
1747 dst[0] = static_cast<uint8>((bl[w + 0] + tl[0] - bl[0] - tl[w + 0]) * ooa);
1748 dst[1] = static_cast<uint8>((bl[w + 1] + tl[1] - bl[1] - tl[w + 1]) * ooa);
1749 dst[2] = static_cast<uint8>((bl[w + 2] + tl[2] - bl[2] - tl[w + 2]) * ooa);
1750 dst[3] = static_cast<uint8>((bl[w + 3] + tl[3] - bl[3] - tl[w + 3]) * ooa);
1757 // Copy pixels from rotated source to destination row with a slope.
1759 void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride,
1760 uint8* dst_argb, const float* uv_dudv, int width) {
1761 // Render a row of pixels from source into a buffer.
1765 for (int i = 0; i < width; ++i) {
1766 int x = static_cast<int>(uv[0]);
1767 int y = static_cast<int>(uv[1]);
1768 *reinterpret_cast<uint32*>(dst_argb) =
1769 *reinterpret_cast<const uint32*>(src_argb + y * src_argb_stride +
1772 uv[0] += uv_dudv[2];
1773 uv[1] += uv_dudv[3];
1777 // C version 2x2 -> 2x1.
1778 void InterpolateRow_C(uint8* dst_ptr, const uint8* src_ptr,
1779 ptrdiff_t src_stride,
1780 int width, int source_y_fraction) {
1781 int y1_fraction = source_y_fraction;
1782 int y0_fraction = 256 - y1_fraction;
1783 const uint8* src_ptr1 = src_ptr + src_stride;
1785 for (int x = 0; x < width - 1; x += 2) {
1786 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8;
1787 dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8;
1793 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8;
1797 // Blend 2 rows into 1 for conversions such as I422ToI420.
1798 void HalfRow_C(const uint8* src_uv, int src_uv_stride,
1799 uint8* dst_uv, int pix) {
1800 for (int x = 0; x < pix; ++x) {
1801 dst_uv[x] = (src_uv[x] + src_uv[src_uv_stride + x] + 1) >> 1;
1805 // Select 2 channels from ARGB on alternating pixels. e.g. BGBGBGBG
1806 void ARGBToBayerRow_C(const uint8* src_argb,
1807 uint8* dst_bayer, uint32 selector, int pix) {
1808 int index0 = selector & 0xff;
1809 int index1 = (selector >> 8) & 0xff;
1810 // Copy a row of Bayer.
1811 for (int x = 0; x < pix - 1; x += 2) {
1812 dst_bayer[0] = src_argb[index0];
1813 dst_bayer[1] = src_argb[index1];
1818 dst_bayer[0] = src_argb[index0];
1822 // Use first 4 shuffler values to reorder ARGB channels.
1823 void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb,
1824 const uint8* shuffler, int pix) {
1825 int index0 = shuffler[0];
1826 int index1 = shuffler[1];
1827 int index2 = shuffler[2];
1828 int index3 = shuffler[3];
1829 // Shuffle a row of ARGB.
1830 for (int x = 0; x < pix; ++x) {
1831 // To support in-place conversion.
1832 uint8 b = src_argb[index0];
1833 uint8 g = src_argb[index1];
1834 uint8 r = src_argb[index2];
1835 uint8 a = src_argb[index3];
1845 void I422ToYUY2Row_C(const uint8* src_y,
1848 uint8* dst_frame, int width) {
1849 for (int x = 0; x < width - 1; x += 2) {
1850 dst_frame[0] = src_y[0];
1851 dst_frame[1] = src_u[0];
1852 dst_frame[2] = src_y[1];
1853 dst_frame[3] = src_v[0];
1860 dst_frame[0] = src_y[0];
1861 dst_frame[1] = src_u[0];
1862 dst_frame[2] = src_y[0]; // duplicate last y
1863 dst_frame[3] = src_v[0];
1867 void I422ToUYVYRow_C(const uint8* src_y,
1870 uint8* dst_frame, int width) {
1871 for (int x = 0; x < width - 1; x += 2) {
1872 dst_frame[0] = src_u[0];
1873 dst_frame[1] = src_y[0];
1874 dst_frame[2] = src_v[0];
1875 dst_frame[3] = src_y[1];
1882 dst_frame[0] = src_u[0];
1883 dst_frame[1] = src_y[0];
1884 dst_frame[2] = src_v[0];
1885 dst_frame[3] = src_y[0]; // duplicate last y
1889 #if !defined(LIBYUV_DISABLE_X86)
1890 // row_win.cc has asm version, but GCC uses 2 step wrapper. 5% slower.
1891 // TODO(fbarchard): Handle width > kMaxStride here instead of calling code.
1892 #if defined(__x86_64__) || defined(__i386__)
1893 void I422ToRGB565Row_SSSE3(const uint8* src_y,
1898 SIMD_ALIGNED(uint8 row[kMaxStride]);
1899 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width);
1900 ARGBToRGB565Row_SSE2(row, rgb_buf, width);
1902 #endif // defined(__x86_64__) || defined(__i386__)
1904 #if defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)
1905 void I422ToARGB1555Row_SSSE3(const uint8* src_y,
1910 SIMD_ALIGNED(uint8 row[kMaxStride]);
1911 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width);
1912 ARGBToARGB1555Row_SSE2(row, rgb_buf, width);
1915 void I422ToARGB4444Row_SSSE3(const uint8* src_y,
1920 SIMD_ALIGNED(uint8 row[kMaxStride]);
1921 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, width);
1922 ARGBToARGB4444Row_SSE2(row, rgb_buf, width);
1925 void NV12ToRGB565Row_SSSE3(const uint8* src_y,
1926 const uint8* src_uv,
1929 SIMD_ALIGNED(uint8 row[kMaxStride]);
1930 NV12ToARGBRow_SSSE3(src_y, src_uv, row, width);
1931 ARGBToRGB565Row_SSE2(row, dst_rgb565, width);
1934 void NV21ToRGB565Row_SSSE3(const uint8* src_y,
1935 const uint8* src_vu,
1938 SIMD_ALIGNED(uint8 row[kMaxStride]);
1939 NV21ToARGBRow_SSSE3(src_y, src_vu, row, width);
1940 ARGBToRGB565Row_SSE2(row, dst_rgb565, width);
1943 void YUY2ToARGBRow_SSSE3(const uint8* src_yuy2,
1946 SIMD_ALIGNED(uint8 row_y[kMaxStride]);
1947 SIMD_ALIGNED(uint8 row_u[kMaxStride / 2]);
1948 SIMD_ALIGNED(uint8 row_v[kMaxStride / 2]);
1949 YUY2ToUV422Row_SSE2(src_yuy2, row_u, row_v, width);
1950 YUY2ToYRow_SSE2(src_yuy2, row_y, width);
1951 I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width);
1954 void YUY2ToARGBRow_Unaligned_SSSE3(const uint8* src_yuy2,
1957 SIMD_ALIGNED(uint8 row_y[kMaxStride]);
1958 SIMD_ALIGNED(uint8 row_u[kMaxStride / 2]);
1959 SIMD_ALIGNED(uint8 row_v[kMaxStride / 2]);
1960 YUY2ToUV422Row_Unaligned_SSE2(src_yuy2, row_u, row_v, width);
1961 YUY2ToYRow_Unaligned_SSE2(src_yuy2, row_y, width);
1962 I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width);
1965 void UYVYToARGBRow_SSSE3(const uint8* src_uyvy,
1968 SIMD_ALIGNED(uint8 row_y[kMaxStride]);
1969 SIMD_ALIGNED(uint8 row_u[kMaxStride / 2]);
1970 SIMD_ALIGNED(uint8 row_v[kMaxStride / 2]);
1971 UYVYToUV422Row_SSE2(src_uyvy, row_u, row_v, width);
1972 UYVYToYRow_SSE2(src_uyvy, row_y, width);
1973 I422ToARGBRow_SSSE3(row_y, row_u, row_v, dst_argb, width);
1976 void UYVYToARGBRow_Unaligned_SSSE3(const uint8* src_uyvy,
1979 SIMD_ALIGNED(uint8 row_y[kMaxStride]);
1980 SIMD_ALIGNED(uint8 row_u[kMaxStride / 2]);
1981 SIMD_ALIGNED(uint8 row_v[kMaxStride / 2]);
1982 UYVYToUV422Row_Unaligned_SSE2(src_uyvy, row_u, row_v, width);
1983 UYVYToYRow_Unaligned_SSE2(src_uyvy, row_y, width);
1984 I422ToARGBRow_Unaligned_SSSE3(row_y, row_u, row_v, dst_argb, width);
1987 #endif // defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)
1988 #endif // !defined(LIBYUV_DISABLE_X86)
1994 } // namespace libyuv