在Android / NDK下,我使用下一个算法将RGB转换为YUV420sp。我开始收到一些用户的少量崩溃报告。因此,在他们向我发送日志之后,在我推出的评论中,在第二个算法 decodeARGB888_YUV420sp 上,下一个算法似乎都失败了,日志显示 SIGILL 错误,我发现它有下一个定义:
非法指令(ANSI)通常表示可执行文件 文件已损坏或使用指向函数的指针的数据 预期
报告全部来自SGSII-skyrocket和Rogers变体以及三星Captivate Glide。而不是所有这些设备,因为其他一些使用这些设备的用户也没有报告任何问题。
这些设备硬件是否有特定的东西?还是任何已知的bug?或者我在代码中做错了什么?
JNIEXPORT void JNICALL Java_com_test_NatLib_decodeBitmapToYuv420sp(JNIEnv *env, jobject javaThis, jobject bitmap, jbyteArray yuv)
{
AndroidBitmapInfo bitmapInfo;
int code;
void *nativeRGBPixels;
if ((code = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
{
return;
}
if ((code = AndroidBitmap_lockPixels(env, bitmap, (void**)&nativeRGBPixels)) < 0)
{
return;
}
char *nativeYuvPixels = (char*)env->GetByteArrayElements(yuv, 0);
decodeARGB888_YUV420sp(nativeRGBPixels, nativeYuvPixels, bitmapInfo.width, bitmapInfo.height);
env->ReleaseByteArrayElements(yuv, (jbyte*)nativeYuvPixels , 0);
AndroidBitmap_unlockPixels(env, bitmap);
}
static void decodeARGB888_YUV420sp(const int *argb, char *yuv, const int width, const int height)
{
const int totalPixels = width * height;
int indexPixel = 0;
int indexY = 0;
int indexUV = totalPixels;
int R, G, B, Y, U, V;
int x, y;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
//--------------------------------------------------------------------
// AT THIS POINT IS WHERE THE LAST LOG WITH SIGILL WAS CAPTURED
//--------------------------------------------------------------------
const int pixelValue = argb[indexPixel];
R = pixelValue & 0xff;
G = (pixelValue & 0xff00) >> 8;
B = (pixelValue & 0xff0000) >> 16;
// RGB to YUV algorithm for component Y
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
// NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2 meaning for
// every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other pixel AND every other scanline
yuv[indexY++] = (char)((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
if (y % 2 == 0 && indexPixel % 2 == 0)
{
// RGB to YUV algorithm for component U & V
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
yuv[indexUV++] = (char)((V < 0) ? 0 : ((V > 255) ? 255 : V));
yuv[indexUV++] = (char)((U < 0) ? 0 : ((U > 255) ? 255 : U));
}
indexPixel++;
}
}
}
答案 0 :(得分:1)
因为它大约是SIGILL
,所以你可能会丢失env
,它的值会变成垃圾,处理器会在内存中执行一些不是指令(text
)而是{{1}的区域}}。那是因为跳跃目标是在data
个实例上计算的。
您可以阅读JNI Tips以了解env
使用的一些指示。
答案 1 :(得分:0)
#ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_ARM_NEON := true
#endif
这是错的。 armeabi-v7a并不一定意味着NEON(例如,Tegra2芯片组)。相反,对NEON优化代码的检查应始终是运行时检查,您可以在NDK中找到有关如何执行该操作的文档。