OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. | 2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 src_argb += 8; | 192 src_argb += 8; |
193 } | 193 } |
194 if (width & 1) { | 194 if (width & 1) { |
195 uint8 b0 = src_argb[0] >> 3; | 195 uint8 b0 = src_argb[0] >> 3; |
196 uint8 g0 = src_argb[1] >> 2; | 196 uint8 g0 = src_argb[1] >> 2; |
197 uint8 r0 = src_argb[2] >> 3; | 197 uint8 r0 = src_argb[2] >> 3; |
198 *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); | 198 *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); |
199 } | 199 } |
200 } | 200 } |
201 | 201 |
| 202 // dither4 is a row of 4 values from 4x4 dither matrix. |
| 203 // The 4x4 matrix contains values to increase RGB. When converting to |
| 204 // fewer bits (565) this provides an ordered dither. |
| 205 // The order in the 4x4 matrix in first byte is upper left. |
| 206 // The 4 values are passed as an int, then referenced as an array, so |
| 207 // endian will not affect order of the original matrix. But the dither4 |
| 208 // will containing the first pixel in the lower byte for little endian |
| 209 // or the upper byte for big endian. |
202 void ARGBToRGB565DitherRow_C(const uint8* src_argb, uint8* dst_rgb, | 210 void ARGBToRGB565DitherRow_C(const uint8* src_argb, uint8* dst_rgb, |
203 const uint8* dither8x8, int width) { | 211 const uint32 dither4, int width) { |
204 int x; | 212 int x; |
205 for (x = 0; x < width - 1; x += 2) { | 213 for (x = 0; x < width - 1; x += 2) { |
206 int dither0 = dither8x8[x & 7] - 128; | 214 int dither0 = ((const unsigned char*)(&dither4))[x & 3]; |
207 int dither1 = dither8x8[(x & 7) + 1] - 128; | 215 int dither1 = ((const unsigned char*)(&dither4))[(x + 1) & 3]; |
208 uint8 b0 = Clamp(src_argb[0] + dither0) >> 3; | 216 uint8 b0 = clamp255(src_argb[0] + dither0) >> 3; |
209 uint8 g0 = Clamp(src_argb[1] + dither0) >> 2; | 217 uint8 g0 = clamp255(src_argb[1] + dither0) >> 2; |
210 uint8 r0 = Clamp(src_argb[2] + dither0) >> 3; | 218 uint8 r0 = clamp255(src_argb[2] + dither0) >> 3; |
211 uint8 b1 = Clamp(src_argb[4] + dither1) >> 3; | 219 uint8 b1 = clamp255(src_argb[4] + dither1) >> 3; |
212 uint8 g1 = Clamp(src_argb[5] + dither1) >> 2; | 220 uint8 g1 = clamp255(src_argb[5] + dither1) >> 2; |
213 uint8 r1 = Clamp(src_argb[6] + dither1) >> 3; | 221 uint8 r1 = clamp255(src_argb[6] + dither1) >> 3; |
214 WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | | 222 WRITEWORD(dst_rgb, b0 | (g0 << 5) | (r0 << 11) | |
215 (b1 << 16) | (g1 << 21) | (r1 << 27)); | 223 (b1 << 16) | (g1 << 21) | (r1 << 27)); |
216 dst_rgb += 4; | 224 dst_rgb += 4; |
217 src_argb += 8; | 225 src_argb += 8; |
218 } | 226 } |
219 if (width & 1) { | 227 if (width & 1) { |
220 int dither0 = dither8x8[(width - 1) & 7] - 128; | 228 int dither0 = ((const unsigned char*)(&dither4))[(width - 1) & 3]; |
221 uint8 b0 = Clamp(src_argb[0] + dither0) >> 3; | 229 uint8 b0 = clamp255(src_argb[0] + dither0) >> 3; |
222 uint8 g0 = Clamp(src_argb[1] + dither0) >> 2; | 230 uint8 g0 = clamp255(src_argb[1] + dither0) >> 2; |
223 uint8 r0 = Clamp(src_argb[2] + dither0) >> 3; | 231 uint8 r0 = clamp255(src_argb[2] + dither0) >> 3; |
224 *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); | 232 *(uint16*)(dst_rgb) = b0 | (g0 << 5) | (r0 << 11); |
225 } | 233 } |
226 } | 234 } |
227 | 235 |
228 void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { | 236 void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { |
229 int x; | 237 int x; |
230 for (x = 0; x < width - 1; x += 2) { | 238 for (x = 0; x < width - 1; x += 2) { |
231 uint8 b0 = src_argb[0] >> 3; | 239 uint8 b0 = src_argb[0] >> 3; |
232 uint8 g0 = src_argb[1] >> 3; | 240 uint8 g0 = src_argb[1] >> 3; |
233 uint8 r0 = src_argb[2] >> 3; | 241 uint8 r0 = src_argb[2] >> 3; |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 int b = src_sobely[i]; | 975 int b = src_sobely[i]; |
968 int g = clamp255(r + b); | 976 int g = clamp255(r + b); |
969 dst_argb[0] = (uint8)(b); | 977 dst_argb[0] = (uint8)(b); |
970 dst_argb[1] = (uint8)(g); | 978 dst_argb[1] = (uint8)(g); |
971 dst_argb[2] = (uint8)(r); | 979 dst_argb[2] = (uint8)(r); |
972 dst_argb[3] = (uint8)(255u); | 980 dst_argb[3] = (uint8)(255u); |
973 dst_argb += 4; | 981 dst_argb += 4; |
974 } | 982 } |
975 } | 983 } |
976 | 984 |
977 void I400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { | 985 void J400ToARGBRow_C(const uint8* src_y, uint8* dst_argb, int width) { |
978 // Copy a Y to RGB. | 986 // Copy a Y to RGB. |
979 int x; | 987 int x; |
980 for (x = 0; x < width; ++x) { | 988 for (x = 0; x < width; ++x) { |
981 uint8 y = src_y[0]; | 989 uint8 y = src_y[0]; |
982 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; | 990 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; |
983 dst_argb[3] = 255u; | 991 dst_argb[3] = 255u; |
984 dst_argb += 4; | 992 dst_argb += 4; |
985 ++src_y; | 993 ++src_y; |
986 } | 994 } |
987 } | 995 } |
988 | 996 |
989 // YUV to RGB conversion constants. | 997 // BT.601 YUV to RGB reference |
| 998 // R = (Y - 16) * 1.164 - V * -1.596 |
| 999 // G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 |
| 1000 // B = (Y - 16) * 1.164 - U * -2.018 |
| 1001 |
990 // Y contribution to R,G,B. Scale and bias. | 1002 // Y contribution to R,G,B. Scale and bias. |
991 // TODO(fbarchard): Consider moving constants into a common header. | 1003 // TODO(fbarchard): Consider moving constants into a common header. |
992 #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ | 1004 #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ |
993 #define YGB 1160 /* 1.164 * 64 * 16 - adjusted for even error distribution */ | 1005 #define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ |
994 | 1006 |
995 // U and V contributions to R,G,B. | 1007 // U and V contributions to R,G,B. |
996 #define UB -128 /* -min(128, round(2.018 * 64)) */ | 1008 #define UB -128 /* max(-128, round(-2.018 * 64)) */ |
997 #define UG 25 /* -round(-0.391 * 64) */ | 1009 #define UG 25 /* round(0.391 * 64) */ |
998 #define VG 52 /* -round(-0.813 * 64) */ | 1010 #define VG 52 /* round(0.813 * 64) */ |
999 #define VR -102 /* -round(1.596 * 64) */ | 1011 #define VR -102 /* round(-1.596 * 64) */ |
1000 | 1012 |
1001 // Bias values to subtract 16 from Y and 128 from U and V. | 1013 // Bias values to subtract 16 from Y and 128 from U and V. |
1002 #define BB (UB * 128 - YGB) | 1014 #define BB (UB * 128 + YGB) |
1003 #define BG (UG * 128 + VG * 128 - YGB) | 1015 #define BG (UG * 128 + VG * 128 + YGB) |
1004 #define BR (VR * 128 - YGB) | 1016 #define BR (VR * 128 + YGB) |
1005 | 1017 |
1006 // C reference code that mimics the YUV assembly. | 1018 // C reference code that mimics the YUV assembly. |
1007 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, | 1019 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, |
1008 uint8* b, uint8* g, uint8* r) { | 1020 uint8* b, uint8* g, uint8* r) { |
1009 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; | 1021 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; |
1010 *b = Clamp((int32)(BB - ( u * UB) + y1) >> 6); | 1022 *b = Clamp((int32)(-(u * UB) + y1 + BB) >> 6); |
1011 *g = Clamp((int32)(BG - (v * VG + u * UG) + y1) >> 6); | 1023 *g = Clamp((int32)(-(v * VG + u * UG) + y1 + BG) >> 6); |
1012 *r = Clamp((int32)(BR - (v * VR ) + y1) >> 6); | 1024 *r = Clamp((int32)(-(v * VR)+ y1 + BR) >> 6); |
1013 } | 1025 } |
1014 | 1026 |
1015 // C reference code that mimics the YUV assembly. | 1027 // C reference code that mimics the YUV assembly. |
1016 static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) { | 1028 static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) { |
1017 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; | 1029 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; |
1018 *b = Clamp((int32)(y1 - YGB) >> 6); | 1030 *b = Clamp((int32)(y1 + YGB) >> 6); |
1019 *g = Clamp((int32)(y1 - YGB) >> 6); | 1031 *g = Clamp((int32)(y1 + YGB) >> 6); |
1020 *r = Clamp((int32)(y1 - YGB) >> 6); | 1032 *r = Clamp((int32)(y1 + YGB) >> 6); |
1021 } | 1033 } |
1022 | 1034 |
1023 #undef YG | 1035 #undef YG |
1024 #undef YGB | 1036 #undef YGB |
1025 #undef UB | 1037 #undef UB |
1026 #undef UG | 1038 #undef UG |
1027 #undef VG | 1039 #undef VG |
1028 #undef VR | 1040 #undef VR |
1029 #undef BB | 1041 #undef BB |
1030 #undef BG | 1042 #undef BG |
1031 #undef BR | 1043 #undef BR |
1032 | 1044 |
| 1045 // JPEG YUV to RGB reference |
| 1046 // * R = Y - V * -1.40200 |
| 1047 // * G = Y - U * 0.34414 - V * 0.71414 |
| 1048 // * B = Y - U * -1.77200 |
| 1049 |
| 1050 // Y contribution to R,G,B. Scale and bias. |
| 1051 // TODO(fbarchard): Consider moving constants into a common header. |
| 1052 #define YGJ 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ |
| 1053 #define YGBJ 32 /* 64 / 2 */ |
| 1054 |
| 1055 // U and V contributions to R,G,B. |
| 1056 #define UBJ -113 /* round(-1.77200 * 64) */ |
| 1057 #define UGJ 22 /* round(0.34414 * 64) */ |
| 1058 #define VGJ 46 /* round(0.71414 * 64) */ |
| 1059 #define VRJ -90 /* round(-1.40200 * 64) */ |
| 1060 |
| 1061 // Bias values to subtract 16 from Y and 128 from U and V. |
| 1062 #define BBJ (UBJ * 128 + YGBJ) |
| 1063 #define BGJ (UGJ * 128 + VGJ * 128 + YGBJ) |
| 1064 #define BRJ (VRJ * 128 + YGBJ) |
| 1065 |
| 1066 // C reference code that mimics the YUV assembly. |
| 1067 static __inline void YuvJPixel(uint8 y, uint8 u, uint8 v, |
| 1068 uint8* b, uint8* g, uint8* r) { |
| 1069 uint32 y1 = (uint32)(y * 0x0101 * YGJ) >> 16; |
| 1070 *b = Clamp((int32)(-(u * UBJ) + y1 + BBJ) >> 6); |
| 1071 *g = Clamp((int32)(-(v * VGJ + u * UGJ) + y1 + BGJ) >> 6); |
| 1072 *r = Clamp((int32)(-(v * VRJ) + y1 + BRJ) >> 6); |
| 1073 } |
| 1074 |
| 1075 #undef YGJ |
| 1076 #undef YGBJ |
| 1077 #undef UBJ |
| 1078 #undef UGJ |
| 1079 #undef VGJ |
| 1080 #undef VRJ |
| 1081 #undef BBJ |
| 1082 #undef BGJ |
| 1083 #undef BRJ |
| 1084 |
1033 #if !defined(LIBYUV_DISABLE_NEON) && \ | 1085 #if !defined(LIBYUV_DISABLE_NEON) && \ |
1034 (defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON)) | 1086 (defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON)) |
1035 // C mimic assembly. | 1087 // C mimic assembly. |
1036 // TODO(fbarchard): Remove subsampling from Neon. | 1088 // TODO(fbarchard): Remove subsampling from Neon. |
1037 void I444ToARGBRow_C(const uint8* src_y, | 1089 void I444ToARGBRow_C(const uint8* src_y, |
1038 const uint8* src_u, | 1090 const uint8* src_u, |
1039 const uint8* src_v, | 1091 const uint8* src_v, |
1040 uint8* rgb_buf, | 1092 uint8* rgb_buf, |
1041 int width) { | 1093 int width) { |
1042 int x; | 1094 int x; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 src_v += 1; | 1147 src_v += 1; |
1096 rgb_buf += 8; // Advance 2 pixels. | 1148 rgb_buf += 8; // Advance 2 pixels. |
1097 } | 1149 } |
1098 if (width & 1) { | 1150 if (width & 1) { |
1099 YuvPixel(src_y[0], src_u[0], src_v[0], | 1151 YuvPixel(src_y[0], src_u[0], src_v[0], |
1100 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1152 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1101 rgb_buf[3] = 255; | 1153 rgb_buf[3] = 255; |
1102 } | 1154 } |
1103 } | 1155 } |
1104 | 1156 |
1105 // C reference code that mimics the YUV assembly. | |
1106 // * R = Y + 1.40200 * Cr | |
1107 // * G = Y - 0.34414 * Cb - 0.71414 * Cr | |
1108 // * B = Y + 1.77200 * Cb | |
1109 | |
1110 #define YGJ 64 /* (int8)round(1.000 * 64) */ | |
1111 | |
1112 #define UBJ 113 /* (int8)round(1.772 * 64) */ | |
1113 #define UGJ -22 /* (int8)round(-0.34414 * 64) */ | |
1114 #define URJ 0 | |
1115 | |
1116 #define VBJ 0 | |
1117 #define VGJ -46 /* (int8)round(-0.71414 * 64) */ | |
1118 #define VRJ 90 /* (int8)round(1.402 * 64) */ | |
1119 | |
1120 // Bias | |
1121 #define BBJ (UBJ * 128 + VBJ * 128) | |
1122 #define BGJ (UGJ * 128 + VGJ * 128) | |
1123 #define BRJ (URJ * 128 + VRJ * 128) | |
1124 | |
1125 static __inline void YuvJPixel(uint8 y, uint8 u, uint8 v, | |
1126 uint8* b, uint8* g, uint8* r) { | |
1127 uint32 y1 = (uint32)(y * YGJ); | |
1128 *b = Clamp((int32)(u * UBJ + v * VBJ + y1 - BBJ) >> 6); | |
1129 *g = Clamp((int32)(u * UGJ + v * VGJ + y1 - BGJ) >> 6); | |
1130 *r = Clamp((int32)(u * URJ + v * VRJ + y1 - BRJ) >> 6); | |
1131 } | |
1132 | |
1133 void J422ToARGBRow_C(const uint8* src_y, | 1157 void J422ToARGBRow_C(const uint8* src_y, |
1134 const uint8* src_u, | 1158 const uint8* src_u, |
1135 const uint8* src_v, | 1159 const uint8* src_v, |
1136 uint8* rgb_buf, | 1160 uint8* rgb_buf, |
1137 int width) { | 1161 int width) { |
1138 int x; | 1162 int x; |
1139 for (x = 0; x < width - 1; x += 2) { | 1163 for (x = 0; x < width - 1; x += 2) { |
1140 YuvJPixel(src_y[0], src_u[0], src_v[0], | 1164 YuvJPixel(src_y[0], src_u[0], src_v[0], |
1141 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1165 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1142 rgb_buf[3] = 255; | 1166 rgb_buf[3] = 255; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 rgb_buf += 8; // Advance 2 pixels. | 1371 rgb_buf += 8; // Advance 2 pixels. |
1348 } | 1372 } |
1349 if (width & 1) { | 1373 if (width & 1) { |
1350 YuvPixel(src_y[0], src_u[0], src_v[0], | 1374 YuvPixel(src_y[0], src_u[0], src_v[0], |
1351 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1375 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1352 rgb_buf[3] = 255; | 1376 rgb_buf[3] = 255; |
1353 } | 1377 } |
1354 } | 1378 } |
1355 | 1379 |
1356 void NV12ToARGBRow_C(const uint8* src_y, | 1380 void NV12ToARGBRow_C(const uint8* src_y, |
1357 const uint8* usrc_v, | 1381 const uint8* src_uv, |
1358 uint8* rgb_buf, | 1382 uint8* rgb_buf, |
1359 int width) { | 1383 int width) { |
1360 int x; | 1384 int x; |
1361 for (x = 0; x < width - 1; x += 2) { | 1385 for (x = 0; x < width - 1; x += 2) { |
1362 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], | 1386 YuvPixel(src_y[0], src_uv[0], src_uv[1], |
1363 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1387 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1364 rgb_buf[3] = 255; | 1388 rgb_buf[3] = 255; |
1365 YuvPixel(src_y[1], usrc_v[0], usrc_v[1], | 1389 YuvPixel(src_y[1], src_uv[0], src_uv[1], |
1366 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); | 1390 rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
1367 rgb_buf[7] = 255; | 1391 rgb_buf[7] = 255; |
1368 src_y += 2; | 1392 src_y += 2; |
1369 usrc_v += 2; | 1393 src_uv += 2; |
1370 rgb_buf += 8; // Advance 2 pixels. | 1394 rgb_buf += 8; // Advance 2 pixels. |
1371 } | 1395 } |
1372 if (width & 1) { | 1396 if (width & 1) { |
1373 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], | 1397 YuvPixel(src_y[0], src_uv[0], src_uv[1], |
1374 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1398 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1375 rgb_buf[3] = 255; | 1399 rgb_buf[3] = 255; |
1376 } | 1400 } |
1377 } | 1401 } |
1378 | 1402 |
1379 void NV21ToARGBRow_C(const uint8* src_y, | 1403 void NV21ToARGBRow_C(const uint8* src_y, |
1380 const uint8* src_vu, | 1404 const uint8* src_vu, |
1381 uint8* rgb_buf, | 1405 uint8* rgb_buf, |
1382 int width) { | 1406 int width) { |
1383 int x; | 1407 int x; |
(...skipping 11 matching lines...) Expand all Loading... |
1395 rgb_buf += 8; // Advance 2 pixels. | 1419 rgb_buf += 8; // Advance 2 pixels. |
1396 } | 1420 } |
1397 if (width & 1) { | 1421 if (width & 1) { |
1398 YuvPixel(src_y[0], src_vu[1], src_vu[0], | 1422 YuvPixel(src_y[0], src_vu[1], src_vu[0], |
1399 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1423 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1400 rgb_buf[3] = 255; | 1424 rgb_buf[3] = 255; |
1401 } | 1425 } |
1402 } | 1426 } |
1403 | 1427 |
1404 void NV12ToRGB565Row_C(const uint8* src_y, | 1428 void NV12ToRGB565Row_C(const uint8* src_y, |
1405 const uint8* usrc_v, | 1429 const uint8* src_uv, |
1406 uint8* dst_rgb565, | 1430 uint8* dst_rgb565, |
1407 int width) { | 1431 int width) { |
1408 uint8 b0; | 1432 uint8 b0; |
1409 uint8 g0; | 1433 uint8 g0; |
1410 uint8 r0; | 1434 uint8 r0; |
1411 uint8 b1; | 1435 uint8 b1; |
1412 uint8 g1; | 1436 uint8 g1; |
1413 uint8 r1; | 1437 uint8 r1; |
1414 int x; | 1438 int x; |
1415 for (x = 0; x < width - 1; x += 2) { | 1439 for (x = 0; x < width - 1; x += 2) { |
1416 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); | 1440 YuvPixel(src_y[0], src_uv[0], src_uv[1], &b0, &g0, &r0); |
1417 YuvPixel(src_y[1], usrc_v[0], usrc_v[1], &b1, &g1, &r1); | 1441 YuvPixel(src_y[1], src_uv[0], src_uv[1], &b1, &g1, &r1); |
1418 b0 = b0 >> 3; | 1442 b0 = b0 >> 3; |
1419 g0 = g0 >> 2; | 1443 g0 = g0 >> 2; |
1420 r0 = r0 >> 3; | 1444 r0 = r0 >> 3; |
1421 b1 = b1 >> 3; | 1445 b1 = b1 >> 3; |
1422 g1 = g1 >> 2; | 1446 g1 = g1 >> 2; |
1423 r1 = r1 >> 3; | 1447 r1 = r1 >> 3; |
1424 *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | | 1448 *(uint32*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11) | |
1425 (b1 << 16) | (g1 << 21) | (r1 << 27); | 1449 (b1 << 16) | (g1 << 21) | (r1 << 27); |
1426 src_y += 2; | 1450 src_y += 2; |
1427 usrc_v += 2; | 1451 src_uv += 2; |
1428 dst_rgb565 += 4; // Advance 2 pixels. | 1452 dst_rgb565 += 4; // Advance 2 pixels. |
1429 } | 1453 } |
1430 if (width & 1) { | 1454 if (width & 1) { |
1431 YuvPixel(src_y[0], usrc_v[0], usrc_v[1], &b0, &g0, &r0); | 1455 YuvPixel(src_y[0], src_uv[0], src_uv[1], &b0, &g0, &r0); |
1432 b0 = b0 >> 3; | 1456 b0 = b0 >> 3; |
1433 g0 = g0 >> 2; | 1457 g0 = g0 >> 2; |
1434 r0 = r0 >> 3; | 1458 r0 = r0 >> 3; |
1435 *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); | 1459 *(uint16*)(dst_rgb565) = b0 | (g0 << 5) | (r0 << 11); |
1436 } | 1460 } |
1437 } | 1461 } |
1438 | 1462 |
1439 void NV21ToRGB565Row_C(const uint8* src_y, | 1463 void NV21ToRGB565Row_C(const uint8* src_y, |
1440 const uint8* vsrc_u, | 1464 const uint8* vsrc_u, |
1441 uint8* dst_rgb565, | 1465 uint8* dst_rgb565, |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 src_v += 1; | 1605 src_v += 1; |
1582 rgb_buf += 8; // Advance 2 pixels. | 1606 rgb_buf += 8; // Advance 2 pixels. |
1583 } | 1607 } |
1584 if (width & 1) { | 1608 if (width & 1) { |
1585 YuvPixel(src_y[0], src_u[0], src_v[0], | 1609 YuvPixel(src_y[0], src_u[0], src_v[0], |
1586 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); | 1610 rgb_buf + 1, rgb_buf + 2, rgb_buf + 3); |
1587 rgb_buf[0] = 255; | 1611 rgb_buf[0] = 255; |
1588 } | 1612 } |
1589 } | 1613 } |
1590 | 1614 |
1591 void YToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) { | 1615 void I400ToARGBRow_C(const uint8* src_y, uint8* rgb_buf, int width) { |
1592 int x; | 1616 int x; |
1593 for (x = 0; x < width - 1; x += 2) { | 1617 for (x = 0; x < width - 1; x += 2) { |
1594 YPixel(src_y[0], rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); | 1618 YPixel(src_y[0], rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); |
1595 rgb_buf[3] = 255; | 1619 rgb_buf[3] = 255; |
1596 YPixel(src_y[1], rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); | 1620 YPixel(src_y[1], rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); |
1597 rgb_buf[7] = 255; | 1621 rgb_buf[7] = 255; |
1598 src_y += 2; | 1622 src_y += 2; |
1599 rgb_buf += 8; // Advance 2 pixels. | 1623 rgb_buf += 8; // Advance 2 pixels. |
1600 } | 1624 } |
1601 if (width & 1) { | 1625 if (width & 1) { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8; | 2079 dst_ptr[1] = (src_ptr[1] * y0_fraction + src_ptr1[1] * y1_fraction) >> 8; |
2056 src_ptr += 2; | 2080 src_ptr += 2; |
2057 src_ptr1 += 2; | 2081 src_ptr1 += 2; |
2058 dst_ptr += 2; | 2082 dst_ptr += 2; |
2059 } | 2083 } |
2060 if (width & 1) { | 2084 if (width & 1) { |
2061 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; | 2085 dst_ptr[0] = (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction) >> 8; |
2062 } | 2086 } |
2063 } | 2087 } |
2064 | 2088 |
2065 // Select G channel from ARGB. e.g. GGGGGGGG | |
2066 void ARGBToBayerGGRow_C(const uint8* src_argb, | |
2067 uint8* dst_bayer, uint32 selector, int pix) { | |
2068 // Copy a row of G. | |
2069 int x; | |
2070 for (x = 0; x < pix - 1; x += 2) { | |
2071 dst_bayer[0] = src_argb[1]; | |
2072 dst_bayer[1] = src_argb[5]; | |
2073 src_argb += 8; | |
2074 dst_bayer += 2; | |
2075 } | |
2076 if (pix & 1) { | |
2077 dst_bayer[0] = src_argb[1]; | |
2078 } | |
2079 } | |
2080 | |
2081 // Use first 4 shuffler values to reorder ARGB channels. | 2089 // Use first 4 shuffler values to reorder ARGB channels. |
2082 void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, | 2090 void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, |
2083 const uint8* shuffler, int pix) { | 2091 const uint8* shuffler, int pix) { |
2084 int index0 = shuffler[0]; | 2092 int index0 = shuffler[0]; |
2085 int index1 = shuffler[1]; | 2093 int index1 = shuffler[1]; |
2086 int index2 = shuffler[2]; | 2094 int index2 = shuffler[2]; |
2087 int index3 = shuffler[3]; | 2095 int index3 = shuffler[3]; |
2088 // Shuffle a row of ARGB. | 2096 // Shuffle a row of ARGB. |
2089 int x; | 2097 int x; |
2090 for (x = 0; x < pix; ++x) { | 2098 for (x = 0; x < pix; ++x) { |
(...skipping 22 matching lines...) Expand all Loading... |
2113 dst_frame[2] = src_y[1]; | 2121 dst_frame[2] = src_y[1]; |
2114 dst_frame[3] = src_v[0]; | 2122 dst_frame[3] = src_v[0]; |
2115 dst_frame += 4; | 2123 dst_frame += 4; |
2116 src_y += 2; | 2124 src_y += 2; |
2117 src_u += 1; | 2125 src_u += 1; |
2118 src_v += 1; | 2126 src_v += 1; |
2119 } | 2127 } |
2120 if (width & 1) { | 2128 if (width & 1) { |
2121 dst_frame[0] = src_y[0]; | 2129 dst_frame[0] = src_y[0]; |
2122 dst_frame[1] = src_u[0]; | 2130 dst_frame[1] = src_u[0]; |
2123 dst_frame[2] = src_y[0]; // duplicate last y | 2131 dst_frame[2] = 0; |
2124 dst_frame[3] = src_v[0]; | 2132 dst_frame[3] = src_v[0]; |
2125 } | 2133 } |
2126 } | 2134 } |
2127 | 2135 |
2128 void I422ToUYVYRow_C(const uint8* src_y, | 2136 void I422ToUYVYRow_C(const uint8* src_y, |
2129 const uint8* src_u, | 2137 const uint8* src_u, |
2130 const uint8* src_v, | 2138 const uint8* src_v, |
2131 uint8* dst_frame, int width) { | 2139 uint8* dst_frame, int width) { |
2132 int x; | 2140 int x; |
2133 for (x = 0; x < width - 1; x += 2) { | 2141 for (x = 0; x < width - 1; x += 2) { |
2134 dst_frame[0] = src_u[0]; | 2142 dst_frame[0] = src_u[0]; |
2135 dst_frame[1] = src_y[0]; | 2143 dst_frame[1] = src_y[0]; |
2136 dst_frame[2] = src_v[0]; | 2144 dst_frame[2] = src_v[0]; |
2137 dst_frame[3] = src_y[1]; | 2145 dst_frame[3] = src_y[1]; |
2138 dst_frame += 4; | 2146 dst_frame += 4; |
2139 src_y += 2; | 2147 src_y += 2; |
2140 src_u += 1; | 2148 src_u += 1; |
2141 src_v += 1; | 2149 src_v += 1; |
2142 } | 2150 } |
2143 if (width & 1) { | 2151 if (width & 1) { |
2144 dst_frame[0] = src_u[0]; | 2152 dst_frame[0] = src_u[0]; |
2145 dst_frame[1] = src_y[0]; | 2153 dst_frame[1] = src_y[0]; |
2146 dst_frame[2] = src_v[0]; | 2154 dst_frame[2] = src_v[0]; |
2147 dst_frame[3] = src_y[0]; // duplicate last y | 2155 dst_frame[3] = 0; |
2148 } | 2156 } |
2149 } | 2157 } |
2150 | 2158 |
2151 // Maximum temporary width for wrappers to process at a time, in pixels. | 2159 // Maximum temporary width for wrappers to process at a time, in pixels. |
2152 #define MAXTWIDTH 2048 | 2160 #define MAXTWIDTH 2048 |
2153 | 2161 |
2154 #if !defined(_MSC_VER) && defined(HAS_I422TORGB565ROW_SSSE3) | 2162 #if !(defined(_MSC_VER) && !defined(__clang__)) && \ |
| 2163 defined(HAS_I422TORGB565ROW_SSSE3) |
2155 // row_win.cc has asm version, but GCC uses 2 step wrapper. | 2164 // row_win.cc has asm version, but GCC uses 2 step wrapper. |
2156 void I422ToRGB565Row_SSSE3(const uint8* src_y, | 2165 void I422ToRGB565Row_SSSE3(const uint8* src_y, |
2157 const uint8* src_u, | 2166 const uint8* src_u, |
2158 const uint8* src_v, | 2167 const uint8* src_v, |
2159 uint8* dst_rgb565, | 2168 uint8* dst_rgb565, |
2160 int width) { | 2169 int width) { |
2161 SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); | 2170 SIMD_ALIGNED(uint8 row[MAXTWIDTH * 4]); |
2162 while (width > 0) { | 2171 while (width > 0) { |
2163 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; | 2172 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; |
2164 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, twidth); | 2173 I422ToARGBRow_SSSE3(src_y, src_u, src_v, row, twidth); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 ARGBToARGB4444Row_AVX2(row, dst_argb4444, twidth); | 2348 ARGBToARGB4444Row_AVX2(row, dst_argb4444, twidth); |
2340 src_y += twidth; | 2349 src_y += twidth; |
2341 src_u += twidth / 2; | 2350 src_u += twidth / 2; |
2342 src_v += twidth / 2; | 2351 src_v += twidth / 2; |
2343 dst_argb4444 += twidth * 2; | 2352 dst_argb4444 += twidth * 2; |
2344 width -= twidth; | 2353 width -= twidth; |
2345 } | 2354 } |
2346 } | 2355 } |
2347 #endif | 2356 #endif |
2348 | 2357 |
| 2358 #if defined(HAS_I422TORGB24ROW_AVX2) |
| 2359 void I422ToRGB24Row_AVX2(const uint8* src_y, |
| 2360 const uint8* src_u, |
| 2361 const uint8* src_v, |
| 2362 uint8* dst_rgb24, |
| 2363 int width) { |
| 2364 // Row buffer for intermediate ARGB pixels. |
| 2365 SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); |
| 2366 while (width > 0) { |
| 2367 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; |
| 2368 I422ToARGBRow_AVX2(src_y, src_u, src_v, row, twidth); |
| 2369 // TODO(fbarchard): ARGBToRGB24Row_AVX2 |
| 2370 ARGBToRGB24Row_SSSE3(row, dst_rgb24, twidth); |
| 2371 src_y += twidth; |
| 2372 src_u += twidth / 2; |
| 2373 src_v += twidth / 2; |
| 2374 dst_rgb24 += twidth * 3; |
| 2375 width -= twidth; |
| 2376 } |
| 2377 } |
| 2378 #endif |
| 2379 |
| 2380 #if defined(HAS_I422TORAWROW_AVX2) |
| 2381 void I422ToRAWRow_AVX2(const uint8* src_y, |
| 2382 const uint8* src_u, |
| 2383 const uint8* src_v, |
| 2384 uint8* dst_raw, |
| 2385 int width) { |
| 2386 // Row buffer for intermediate ARGB pixels. |
| 2387 SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); |
| 2388 while (width > 0) { |
| 2389 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; |
| 2390 I422ToARGBRow_AVX2(src_y, src_u, src_v, row, twidth); |
| 2391 // TODO(fbarchard): ARGBToRAWRow_AVX2 |
| 2392 ARGBToRAWRow_SSSE3(row, dst_raw, twidth); |
| 2393 src_y += twidth; |
| 2394 src_u += twidth / 2; |
| 2395 src_v += twidth / 2; |
| 2396 dst_raw += twidth * 3; |
| 2397 width -= twidth; |
| 2398 } |
| 2399 } |
| 2400 #endif |
| 2401 |
2349 #if defined(HAS_NV12TORGB565ROW_AVX2) | 2402 #if defined(HAS_NV12TORGB565ROW_AVX2) |
2350 void NV12ToRGB565Row_AVX2(const uint8* src_y, const uint8* src_uv, | 2403 void NV12ToRGB565Row_AVX2(const uint8* src_y, const uint8* src_uv, |
2351 uint8* dst_rgb565, int width) { | 2404 uint8* dst_rgb565, int width) { |
2352 // Row buffer for intermediate ARGB pixels. | 2405 // Row buffer for intermediate ARGB pixels. |
2353 SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); | 2406 SIMD_ALIGNED32(uint8 row[MAXTWIDTH * 4]); |
2354 while (width > 0) { | 2407 while (width > 0) { |
2355 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; | 2408 int twidth = width > MAXTWIDTH ? MAXTWIDTH : width; |
2356 NV12ToARGBRow_AVX2(src_y, src_uv, row, twidth); | 2409 NV12ToARGBRow_AVX2(src_y, src_uv, row, twidth); |
2357 ARGBToRGB565Row_AVX2(row, dst_rgb565, twidth); | 2410 ARGBToRGB565Row_AVX2(row, dst_rgb565, twidth); |
2358 src_y += twidth; | 2411 src_y += twidth; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 } | 2567 } |
2515 if (width & 1) { | 2568 if (width & 1) { |
2516 dst[3] = src[0]; | 2569 dst[3] = src[0]; |
2517 } | 2570 } |
2518 } | 2571 } |
2519 | 2572 |
2520 #ifdef __cplusplus | 2573 #ifdef __cplusplus |
2521 } // extern "C" | 2574 } // extern "C" |
2522 } // namespace libyuv | 2575 } // namespace libyuv |
2523 #endif | 2576 #endif |
OLD | NEW |