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 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 int x; | 988 int x; |
989 for (x = 0; x < width; ++x) { | 989 for (x = 0; x < width; ++x) { |
990 uint8 y = src_y[0]; | 990 uint8 y = src_y[0]; |
991 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; | 991 dst_argb[2] = dst_argb[1] = dst_argb[0] = y; |
992 dst_argb[3] = 255u; | 992 dst_argb[3] = 255u; |
993 dst_argb += 4; | 993 dst_argb += 4; |
994 ++src_y; | 994 ++src_y; |
995 } | 995 } |
996 } | 996 } |
997 | 997 |
| 998 // TODO(fbarchard): Unify these structures to be platform independent. |
| 999 // TODO(fbarchard): Generate SIMD structures from float matrix. |
| 1000 |
998 // BT.601 YUV to RGB reference | 1001 // BT.601 YUV to RGB reference |
999 // R = (Y - 16) * 1.164 - V * -1.596 | 1002 // R = (Y - 16) * 1.164 - V * -1.596 |
1000 // G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 | 1003 // G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 |
1001 // B = (Y - 16) * 1.164 - U * -2.018 | 1004 // B = (Y - 16) * 1.164 - U * -2.018 |
1002 | 1005 |
1003 // Y contribution to R,G,B. Scale and bias. | 1006 // Y contribution to R,G,B. Scale and bias. |
1004 #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ | 1007 #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ |
1005 #define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ | 1008 #define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ |
1006 | 1009 |
1007 // U and V contributions to R,G,B. | 1010 // U and V contributions to R,G,B. |
1008 #define UB -128 /* max(-128, round(-2.018 * 64)) */ | 1011 #define UB -128 /* max(-128, round(-2.018 * 64)) */ |
1009 #define UG 25 /* round(0.391 * 64) */ | 1012 #define UG 25 /* round(0.391 * 64) */ |
1010 #define VG 52 /* round(0.813 * 64) */ | 1013 #define VG 52 /* round(0.813 * 64) */ |
1011 #define VR -102 /* round(-1.596 * 64) */ | 1014 #define VR -102 /* round(-1.596 * 64) */ |
1012 | 1015 |
1013 // Bias values to subtract 16 from Y and 128 from U and V. | 1016 // Bias values to subtract 16 from Y and 128 from U and V. |
1014 #define BB (UB * 128 + YGB) | 1017 #define BB (UB * 128 + YGB) |
1015 #define BG (UG * 128 + VG * 128 + YGB) | 1018 #define BG (UG * 128 + VG * 128 + YGB) |
1016 #define BR (VR * 128 + YGB) | 1019 #define BR (VR * 128 + YGB) |
1017 | 1020 |
1018 // BT.601 constants for YUV to RGB. | |
1019 // TODO(fbarchard): Unify these structures to be platform independent. | |
1020 // TODO(fbarchard): Generate SIMD structures from float matrix. | |
1021 #if defined(__aarch64__) | 1021 #if defined(__aarch64__) |
1022 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { | 1022 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { |
1023 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, | 1023 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1024 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, | 1024 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1025 { UG, VG, UG, VG, UG, VG, UG, VG }, | 1025 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1026 { UG, VG, UG, VG, UG, VG, UG, VG }, | 1026 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1027 { BB, BG, BR, 0, 0, 0, 0, 0 }, | 1027 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1028 { 0x0101 * YG, 0, 0, 0 } | 1028 { 0x0101 * YG, 0, 0, 0 } |
1029 }; | 1029 }; |
| 1030 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { |
| 1031 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1032 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1033 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1034 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1035 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1036 { 0x0101 * YG, 0, 0, 0 } |
| 1037 }; |
1030 #elif defined(__arm__) | 1038 #elif defined(__arm__) |
1031 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { | 1039 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { |
1032 { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1040 { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1033 { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1041 { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1034 { BB, BG, BR, 0, 0, 0, 0, 0 }, | 1042 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1035 { 0x0101 * YG, 0, 0, 0 } | 1043 { 0x0101 * YG, 0, 0, 0 } |
1036 }; | 1044 }; |
| 1045 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { |
| 1046 { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1047 { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1048 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1049 { 0x0101 * YG, 0, 0, 0 } |
| 1050 }; |
1037 #else | 1051 #else |
1038 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { | 1052 const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { |
1039 { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, | 1053 { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, |
1040 UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, | 1054 UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, |
1041 { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, | 1055 { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, |
1042 UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, | 1056 UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, |
1043 { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, | 1057 { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, |
1044 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, | 1058 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, |
1045 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, | 1059 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
1046 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, | 1060 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
1047 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, | 1061 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
1048 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } | 1062 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } |
1049 }; | 1063 }; |
1050 #endif | |
1051 | |
1052 // C reference code that mimics the YUV assembly. | |
1053 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, | |
1054 uint8* b, uint8* g, uint8* r, | |
1055 const struct YuvConstants* yuvconstants) { | |
1056 #if defined(__aarch64__) | |
1057 int ub = -yuvconstants->kUVToRB[0]; | |
1058 int ug = yuvconstants->kUVToG[0]; | |
1059 int vg = yuvconstants->kUVToG[1]; | |
1060 int vr = -yuvconstants->kUVToRB[1]; | |
1061 int bb = yuvconstants->kUVBiasBGR[0]; | |
1062 int bg = yuvconstants->kUVBiasBGR[1]; | |
1063 int br = yuvconstants->kUVBiasBGR[2]; | |
1064 int yg = yuvconstants->kYToRgb[0] / 0x0101; | |
1065 #elif defined(__arm__) | |
1066 int ub = -yuvconstants->kUVToRB[0]; | |
1067 int ug = yuvconstants->kUVToG[0]; | |
1068 int vg = yuvconstants->kUVToG[4]; | |
1069 int vr = -yuvconstants->kUVToRB[4]; | |
1070 int bb = yuvconstants->kUVBiasBGR[0]; | |
1071 int bg = yuvconstants->kUVBiasBGR[1]; | |
1072 int br = yuvconstants->kUVBiasBGR[2]; | |
1073 int yg = yuvconstants->kYToRgb[0] / 0x0101; | |
1074 #else | |
1075 int ub = yuvconstants->kUVToB[0]; | |
1076 int ug = yuvconstants->kUVToG[0]; | |
1077 int vg = yuvconstants->kUVToG[1]; | |
1078 int vr = yuvconstants->kUVToR[1]; | |
1079 int bb = yuvconstants->kUVBiasB[0]; | |
1080 int bg = yuvconstants->kUVBiasG[0]; | |
1081 int br = yuvconstants->kUVBiasR[0]; | |
1082 int yg = yuvconstants->kYToRgb[0]; | |
1083 #endif | |
1084 | |
1085 uint32 y1 = (uint32)(y * 0x0101 * yg) >> 16; | |
1086 *b = Clamp((int32)(-(u * ub ) + y1 + bb) >> 6); | |
1087 *g = Clamp((int32)(-(u * ug + v * vg) + y1 + bg) >> 6); | |
1088 *r = Clamp((int32)(-( v * vr) + y1 + br) >> 6); | |
1089 } | |
1090 | |
1091 // C reference code that mimics the YUV assembly. | |
1092 static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) { | |
1093 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; | |
1094 *b = Clamp((int32)(y1 + YGB) >> 6); | |
1095 *g = Clamp((int32)(y1 + YGB) >> 6); | |
1096 *r = Clamp((int32)(y1 + YGB) >> 6); | |
1097 } | |
1098 | |
1099 // BT.601 constants for YVU to BGR. | |
1100 // Allows YUV TO RGB code to implement YUV to BGR by swapping UV and using this | |
1101 // matrix. | |
1102 | |
1103 #if defined(__aarch64__) | |
1104 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { | |
1105 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, | |
1106 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, | |
1107 { VG, UG, VG, UG, VG, UG, VG, UG }, | |
1108 { VG, UG, VG, UG, VG, UG, VG, UG }, | |
1109 { BR, BG, BB, 0, 0, 0, 0, 0 }, | |
1110 { 0x0101 * YG, 0, 0, 0 } | |
1111 }; | |
1112 | |
1113 #elif defined(__arm__) | |
1114 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { | |
1115 { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
1116 { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
1117 { BR, BG, BB, 0, 0, 0, 0, 0 }, | |
1118 { 0x0101 * YG, 0, 0, 0 } | |
1119 }; | |
1120 #else | |
1121 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { | 1064 const YuvConstants SIMD_ALIGNED(kYvuIConstants) = { |
1122 { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, | 1065 { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, |
1123 VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, UB, 0 }, | 1066 VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, UB, 0 }, |
1124 { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, | 1067 { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, |
1125 VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, | 1068 VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, |
1126 { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, | 1069 { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, |
1127 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, VR }, | 1070 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, VR }, |
1128 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, | 1071 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
1129 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, | 1072 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
1130 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, | 1073 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
(...skipping 10 matching lines...) Expand all Loading... |
1141 #undef VG | 1084 #undef VG |
1142 #undef VR | 1085 #undef VR |
1143 #undef YG | 1086 #undef YG |
1144 | 1087 |
1145 // JPEG YUV to RGB reference | 1088 // JPEG YUV to RGB reference |
1146 // * R = Y - V * -1.40200 | 1089 // * R = Y - V * -1.40200 |
1147 // * G = Y - U * 0.34414 - V * 0.71414 | 1090 // * G = Y - U * 0.34414 - V * 0.71414 |
1148 // * B = Y - U * -1.77200 | 1091 // * B = Y - U * -1.77200 |
1149 | 1092 |
1150 // Y contribution to R,G,B. Scale and bias. | 1093 // Y contribution to R,G,B. Scale and bias. |
1151 #define YGJ 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ | 1094 #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ |
1152 #define YGBJ 32 /* 64 / 2 */ | 1095 #define YGB 32 /* 64 / 2 */ |
1153 | 1096 |
1154 // U and V contributions to R,G,B. | 1097 // U and V contributions to R,G,B. |
1155 #define UBJ -113 /* round(-1.77200 * 64) */ | 1098 #define UB -113 /* round(-1.77200 * 64) */ |
1156 #define UGJ 22 /* round(0.34414 * 64) */ | 1099 #define UG 22 /* round(0.34414 * 64) */ |
1157 #define VGJ 46 /* round(0.71414 * 64) */ | 1100 #define VG 46 /* round(0.71414 * 64) */ |
1158 #define VRJ -90 /* round(-1.40200 * 64) */ | 1101 #define VR -90 /* round(-1.40200 * 64) */ |
1159 | 1102 |
1160 // Bias values to round, and subtract 128 from U and V. | 1103 // Bias values to round, and subtract 128 from U and V. |
1161 #define BBJ (UBJ * 128 + YGBJ) | 1104 #define BB (UB * 128 + YGB) |
1162 #define BGJ (UGJ * 128 + VGJ * 128 + YGBJ) | 1105 #define BG (UG * 128 + VG * 128 + YGB) |
1163 #define BRJ (VRJ * 128 + YGBJ) | 1106 #define BR (VR * 128 + YGB) |
1164 | 1107 |
1165 // JPEG constants for YUV to RGB. | |
1166 #if defined(__aarch64__) | 1108 #if defined(__aarch64__) |
1167 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { | 1109 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { |
1168 { -UBJ, -VRJ, -UBJ, -VRJ, -UBJ, -VRJ, -UBJ, -VRJ }, | 1110 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1169 { -UBJ, -VRJ, -UBJ, -VRJ, -UBJ, -VRJ, -UBJ, -VRJ }, | 1111 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1170 { UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ }, | 1112 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1171 { UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ }, | 1113 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1172 { BBJ, BGJ, BRJ, 0, 0, 0, 0, 0 }, | 1114 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1173 { 0x0101 * YGJ, 0, 0, 0 } | 1115 { 0x0101 * YG, 0, 0, 0 } |
1174 }; | 1116 }; |
1175 | 1117 const YuvConstants SIMD_ALIGNED(kYvuJConstants) = { |
| 1118 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1119 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1120 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1121 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1122 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1123 { 0x0101 * YG, 0, 0, 0 } |
| 1124 }; |
1176 #elif defined(__arm__) | 1125 #elif defined(__arm__) |
1177 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { | 1126 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { |
1178 { -UBJ, -UBJ, -UBJ, -UBJ, -VRJ, -VRJ, -VRJ, -VRJ, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1127 { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1179 { UGJ, UGJ, UGJ, UGJ, VGJ, VGJ, VGJ, VGJ, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1128 { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1180 { BBJ, BGJ, BRJ, 0, 0, 0, 0, 0 }, | 1129 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1181 { 0x0101 * YGJ, 0, 0, 0 } | 1130 { 0x0101 * YG, 0, 0, 0 } |
| 1131 }; |
| 1132 const YuvConstants SIMD_ALIGNED(kYvuJConstants) = { |
| 1133 { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1134 { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1135 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1136 { 0x0101 * YG, 0, 0, 0 } |
1182 }; | 1137 }; |
1183 #else | 1138 #else |
1184 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { | 1139 const YuvConstants SIMD_ALIGNED(kYuvJConstants) = { |
1185 { UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, | 1140 { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, |
1186 UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0, UBJ, 0 }, | 1141 UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, |
1187 { UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, | 1142 { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, |
1188 UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, | 1143 UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, |
1189 UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, | 1144 { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, |
1190 UGJ, VGJ, UGJ, VGJ, UGJ, VGJ, UGJ, VGJ }, | 1145 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, |
1191 { 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, | 1146 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
1192 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ, 0, VRJ }, | 1147 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
1193 { BBJ, BBJ, BBJ, BBJ, BBJ, BBJ, BBJ, BBJ, | 1148 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
1194 BBJ, BBJ, BBJ, BBJ, BBJ, BBJ, BBJ, BBJ }, | 1149 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } |
1195 { BGJ, BGJ, BGJ, BGJ, BGJ, BGJ, BGJ, BGJ, | 1150 }; |
1196 BGJ, BGJ, BGJ, BGJ, BGJ, BGJ, BGJ, BGJ }, | 1151 const YuvConstants SIMD_ALIGNED(kYvuJConstants) = { |
1197 { BRJ, BRJ, BRJ, BRJ, BRJ, BRJ, BRJ, BRJ, | 1152 { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, |
1198 BRJ, BRJ, BRJ, BRJ, BRJ, BRJ, BRJ, BRJ }, | 1153 VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, UB, 0 }, |
1199 { YGJ, YGJ, YGJ, YGJ, YGJ, YGJ, YGJ, YGJ, | 1154 { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, |
1200 YGJ, YGJ, YGJ, YGJ, YGJ, YGJ, YGJ, YGJ } | 1155 VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1156 { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, |
| 1157 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, VR }, |
| 1158 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
| 1159 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
| 1160 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
| 1161 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } |
1201 }; | 1162 }; |
1202 #endif | 1163 #endif |
1203 | 1164 |
1204 #undef YGJ | 1165 #undef BB |
1205 #undef YGBJ | 1166 #undef BG |
1206 #undef UBJ | 1167 #undef BR |
1207 #undef UGJ | 1168 #undef YGB |
1208 #undef VGJ | 1169 #undef UB |
1209 #undef VRJ | 1170 #undef UG |
1210 #undef BBJ | 1171 #undef VG |
1211 #undef BGJ | 1172 #undef VR |
1212 #undef BRJ | 1173 #undef YG |
1213 | 1174 |
1214 // BT.709 YUV to RGB reference | 1175 // BT.709 YUV to RGB reference |
1215 // * R = Y - V * -1.28033 | 1176 // * R = Y - V * -1.28033 |
1216 // * G = Y - U * 0.21482 - V * 0.38059 | 1177 // * G = Y - U * 0.21482 - V * 0.38059 |
1217 // * B = Y - U * -2.12798 | 1178 // * B = Y - U * -2.12798 |
1218 | 1179 |
1219 // Y contribution to R,G,B. Scale and bias. | 1180 // Y contribution to R,G,B. Scale and bias. |
1220 #define YGH 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ | 1181 #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ |
1221 #define YGBH 32 /* 64 / 2 */ | 1182 #define YGB 32 /* 64 / 2 */ |
1222 | 1183 |
1223 // TODO(fbarchard): Find way to express 2.12 instead of 2.0. | 1184 // TODO(fbarchard): Find way to express 2.12 instead of 2.0. |
1224 // U and V contributions to R,G,B. | 1185 // U and V contributions to R,G,B. |
1225 #define UBH -128 /* max(-128, round(-2.12798 * 64)) */ | 1186 #define UB -128 /* max(-128, round(-2.12798 * 64)) */ |
1226 #define UGH 14 /* round(0.21482 * 64) */ | 1187 #define UG 14 /* round(0.21482 * 64) */ |
1227 #define VGH 24 /* round(0.38059 * 64) */ | 1188 #define VG 24 /* round(0.38059 * 64) */ |
1228 #define VRH -82 /* round(-1.28033 * 64) */ | 1189 #define VR -82 /* round(-1.28033 * 64) */ |
1229 | 1190 |
1230 // Bias values to round, and subtract 128 from U and V. | 1191 // Bias values to round, and subtract 128 from U and V. |
1231 #define BBH (UBH * 128 + YGBH) | 1192 #define BB (UB * 128 + YGB) |
1232 #define BGH (UGH * 128 + VGH * 128 + YGBH) | 1193 #define BG (UG * 128 + VG * 128 + YGB) |
1233 #define BRH (VRH * 128 + YGBH) | 1194 #define BR (VR * 128 + YGB) |
1234 | 1195 |
1235 // BT.709 constants for YUV to RGB. | |
1236 #if defined(__aarch64__) | 1196 #if defined(__aarch64__) |
1237 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { | 1197 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { |
1238 { -UBH, -VRH, -UBH, -VRH, -UBH, -VRH, -UBH, -VRH }, | 1198 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1239 { -UBH, -VRH, -UBH, -VRH, -UBH, -VRH, -UBH, -VRH }, | 1199 { -UB, -VR, -UB, -VR, -UB, -VR, -UB, -VR }, |
1240 { UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH }, | 1200 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1241 { UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH }, | 1201 { UG, VG, UG, VG, UG, VG, UG, VG }, |
1242 { BBH, BGH, BRH, 0, 0, 0, 0, 0 }, | 1202 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1243 { 0x0101 * YGH, 0, 0, 0 } | 1203 { 0x0101 * YG, 0, 0, 0 } |
1244 }; | 1204 }; |
1245 | 1205 const YuvConstants SIMD_ALIGNED(kYvuHConstants) = { |
| 1206 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1207 { -VR, -UB, -VR, -UB, -VR, -UB, -VR, -UB }, |
| 1208 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1209 { VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1210 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1211 { 0x0101 * YG, 0, 0, 0 } |
| 1212 }; |
1246 #elif defined(__arm__) | 1213 #elif defined(__arm__) |
1247 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { | 1214 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { |
1248 { -UBH, -UBH, -UBH, -UBH, -VRH, -VRH, -VRH, -VRH, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1215 { -UB, -UB, -UB, -UB, -VR, -VR, -VR, -VR, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1249 { UGH, UGH, UGH, UGH, VGH, VGH, VGH, VGH, 0, 0, 0, 0, 0, 0, 0, 0 }, | 1216 { UG, UG, UG, UG, VG, VG, VG, VG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
1250 { BBH, BGH, BRH, 0, 0, 0, 0, 0 }, | 1217 { BB, BG, BR, 0, 0, 0, 0, 0 }, |
1251 { 0x0101 * YGH, 0, 0, 0 } | 1218 { 0x0101 * YG, 0, 0, 0 } |
| 1219 }; |
| 1220 const YuvConstants SIMD_ALIGNED(kYvuHConstants) = { |
| 1221 { -VR, -VR, -VR, -VR, -UB, -UB, -UB, -UB, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1222 { VG, VG, VG, VG, UG, UG, UG, UG, 0, 0, 0, 0, 0, 0, 0, 0 }, |
| 1223 { BR, BG, BB, 0, 0, 0, 0, 0 }, |
| 1224 { 0x0101 * YG, 0, 0, 0 } |
1252 }; | 1225 }; |
1253 #else | 1226 #else |
1254 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { | 1227 const YuvConstants SIMD_ALIGNED(kYuvHConstants) = { |
1255 { UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, | 1228 { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, |
1256 UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0, UBH, 0 }, | 1229 UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, |
1257 { UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH, | 1230 { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, |
1258 UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH, | 1231 UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, |
1259 UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH, | 1232 { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, |
1260 UGH, VGH, UGH, VGH, UGH, VGH, UGH, VGH }, | 1233 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, |
1261 { 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, | 1234 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
1262 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH, 0, VRH }, | 1235 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
1263 { BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH, | 1236 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
1264 BBH, BBH, BBH, BBH, BBH, BBH, BBH, BBH }, | 1237 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } |
1265 { BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH, | 1238 }; |
1266 BGH, BGH, BGH, BGH, BGH, BGH, BGH, BGH }, | 1239 const YuvConstants SIMD_ALIGNED(kYvuHConstants) = { |
1267 { BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH, | 1240 { VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, |
1268 BRH, BRH, BRH, BRH, BRH, BRH, BRH, BRH }, | 1241 VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, UB, 0 }, |
1269 { YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH, | 1242 { VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, |
1270 YGH, YGH, YGH, YGH, YGH, YGH, YGH, YGH } | 1243 VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG }, |
| 1244 { 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, |
| 1245 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, VR }, |
| 1246 { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, |
| 1247 { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, |
| 1248 { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, |
| 1249 { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } |
1271 }; | 1250 }; |
1272 #endif | 1251 #endif |
1273 | 1252 |
1274 #undef YGH | 1253 #undef BB |
1275 #undef YGBH | 1254 #undef BG |
1276 #undef UBH | 1255 #undef BR |
1277 #undef UGH | 1256 #undef YGB |
1278 #undef VGH | 1257 #undef UB |
1279 #undef VRH | 1258 #undef UG |
1280 #undef BBH | 1259 #undef VG |
1281 #undef BGH | 1260 #undef VR |
1282 #undef BRH | 1261 #undef YG |
| 1262 |
| 1263 // C reference code that mimics the YUV assembly. |
| 1264 static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, |
| 1265 uint8* b, uint8* g, uint8* r, |
| 1266 const struct YuvConstants* yuvconstants) { |
| 1267 #if defined(__aarch64__) |
| 1268 int ub = -yuvconstants->kUVToRB[0]; |
| 1269 int ug = yuvconstants->kUVToG[0]; |
| 1270 int vg = yuvconstants->kUVToG[1]; |
| 1271 int vr = -yuvconstants->kUVToRB[1]; |
| 1272 int bb = yuvconstants->kUVBiasBGR[0]; |
| 1273 int bg = yuvconstants->kUVBiasBGR[1]; |
| 1274 int br = yuvconstants->kUVBiasBGR[2]; |
| 1275 int yg = yuvconstants->kYToRgb[0] / 0x0101; |
| 1276 #elif defined(__arm__) |
| 1277 int ub = -yuvconstants->kUVToRB[0]; |
| 1278 int ug = yuvconstants->kUVToG[0]; |
| 1279 int vg = yuvconstants->kUVToG[4]; |
| 1280 int vr = -yuvconstants->kUVToRB[4]; |
| 1281 int bb = yuvconstants->kUVBiasBGR[0]; |
| 1282 int bg = yuvconstants->kUVBiasBGR[1]; |
| 1283 int br = yuvconstants->kUVBiasBGR[2]; |
| 1284 int yg = yuvconstants->kYToRgb[0] / 0x0101; |
| 1285 #else |
| 1286 int ub = yuvconstants->kUVToB[0]; |
| 1287 int ug = yuvconstants->kUVToG[0]; |
| 1288 int vg = yuvconstants->kUVToG[1]; |
| 1289 int vr = yuvconstants->kUVToR[1]; |
| 1290 int bb = yuvconstants->kUVBiasB[0]; |
| 1291 int bg = yuvconstants->kUVBiasG[0]; |
| 1292 int br = yuvconstants->kUVBiasR[0]; |
| 1293 int yg = yuvconstants->kYToRgb[0]; |
| 1294 #endif |
| 1295 |
| 1296 uint32 y1 = (uint32)(y * 0x0101 * yg) >> 16; |
| 1297 *b = Clamp((int32)(-(u * ub ) + y1 + bb) >> 6); |
| 1298 *g = Clamp((int32)(-(u * ug + v * vg) + y1 + bg) >> 6); |
| 1299 *r = Clamp((int32)(-( v * vr) + y1 + br) >> 6); |
| 1300 } |
| 1301 |
| 1302 // Y contribution to R,G,B. Scale and bias. |
| 1303 #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ |
| 1304 #define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ |
| 1305 |
| 1306 // C reference code that mimics the YUV assembly. |
| 1307 static __inline void YPixel(uint8 y, uint8* b, uint8* g, uint8* r) { |
| 1308 uint32 y1 = (uint32)(y * 0x0101 * YG) >> 16; |
| 1309 *b = Clamp((int32)(y1 + YGB) >> 6); |
| 1310 *g = Clamp((int32)(y1 + YGB) >> 6); |
| 1311 *r = Clamp((int32)(y1 + YGB) >> 6); |
| 1312 } |
| 1313 |
| 1314 #undef YG |
| 1315 #undef YGB |
1283 | 1316 |
1284 #if !defined(LIBYUV_DISABLE_NEON) && \ | 1317 #if !defined(LIBYUV_DISABLE_NEON) && \ |
1285 (defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON)) | 1318 (defined(__ARM_NEON__) || defined(__aarch64__) || defined(LIBYUV_NEON)) |
1286 // C mimic assembly. | 1319 // C mimic assembly. |
1287 // TODO(fbarchard): Remove subsampling from Neon. | 1320 // TODO(fbarchard): Remove subsampling from Neon. |
1288 void I444ToARGBRow_C(const uint8* src_y, | 1321 void I444ToARGBRow_C(const uint8* src_y, |
1289 const uint8* src_u, | 1322 const uint8* src_u, |
1290 const uint8* src_v, | 1323 const uint8* src_v, |
1291 uint8* rgb_buf, | 1324 uint8* rgb_buf, |
1292 const struct YuvConstants* yuvconstants, | 1325 const struct YuvConstants* yuvconstants, |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 src_a += 2; | 1413 src_a += 2; |
1381 rgb_buf += 8; // Advance 2 pixels. | 1414 rgb_buf += 8; // Advance 2 pixels. |
1382 } | 1415 } |
1383 if (width & 1) { | 1416 if (width & 1) { |
1384 YuvPixel(src_y[0], src_u[0], src_v[0], | 1417 YuvPixel(src_y[0], src_u[0], src_v[0], |
1385 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | 1418 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); |
1386 rgb_buf[3] = src_a[0]; | 1419 rgb_buf[3] = src_a[0]; |
1387 } | 1420 } |
1388 } | 1421 } |
1389 | 1422 |
1390 void I422ToABGRRow_C(const uint8* src_y, | |
1391 const uint8* src_u, | |
1392 const uint8* src_v, | |
1393 uint8* rgb_buf, | |
1394 const struct YuvConstants* yuvconstants, | |
1395 int width) { | |
1396 int x; | |
1397 for (x = 0; x < width - 1; x += 2) { | |
1398 YuvPixel(src_y[0], src_u[0], src_v[0], | |
1399 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0, yuvconstants); | |
1400 rgb_buf[3] = 255; | |
1401 YuvPixel(src_y[1], src_u[0], src_v[0], | |
1402 rgb_buf + 6, rgb_buf + 5, rgb_buf + 4, yuvconstants); | |
1403 rgb_buf[7] = 255; | |
1404 src_y += 2; | |
1405 src_u += 1; | |
1406 src_v += 1; | |
1407 rgb_buf += 8; // Advance 2 pixels. | |
1408 } | |
1409 if (width & 1) { | |
1410 YuvPixel(src_y[0], src_u[0], src_v[0], | |
1411 rgb_buf + 2, rgb_buf + 1, rgb_buf + 0, yuvconstants); | |
1412 rgb_buf[3] = 255; | |
1413 } | |
1414 } | |
1415 | |
1416 void I422ToRGB24Row_C(const uint8* src_y, | 1423 void I422ToRGB24Row_C(const uint8* src_y, |
1417 const uint8* src_u, | 1424 const uint8* src_u, |
1418 const uint8* src_v, | 1425 const uint8* src_v, |
1419 uint8* rgb_buf, | 1426 uint8* rgb_buf, |
1420 const struct YuvConstants* yuvconstants, | 1427 const struct YuvConstants* yuvconstants, |
1421 int width) { | 1428 int width) { |
1422 int x; | 1429 int x; |
1423 for (x = 0; x < width - 1; x += 2) { | 1430 for (x = 0; x < width - 1; x += 2) { |
1424 YuvPixel(src_y[0], src_u[0], src_v[0], | 1431 YuvPixel(src_y[0], src_u[0], src_v[0], |
1425 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | 1432 rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); |
(...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2662 dst_rgb565 += twidth * 2; | 2669 dst_rgb565 += twidth * 2; |
2663 width -= twidth; | 2670 width -= twidth; |
2664 } | 2671 } |
2665 } | 2672 } |
2666 #endif | 2673 #endif |
2667 | 2674 |
2668 #ifdef __cplusplus | 2675 #ifdef __cplusplus |
2669 } // extern "C" | 2676 } // extern "C" |
2670 } // namespace libyuv | 2677 } // namespace libyuv |
2671 #endif | 2678 #endif |
OLD | NEW |