我正在努力寻找Android Studio中Native C中发生的崩溃。
我们知道错误源自Native C中的库。很可能来自垃圾处理程序。 我们试图以不同方式释放变量但尚未成功。奇怪的部分代码适用于Android 5.0及以上版本。
我还通过添加
来搜索如何在Android studio中调试NDKEnable app debugging in your AndroidManifest.xml file by including an <application> element that sets the android:debuggable attribute to true.
并添加日志:
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "The value R %f G %f B %f , H %f S %f V %f ", rgbData[0], rgbData[1], rgbData[2], rgbData[3], rgbData[4], rgbData[5]);
但是,显示器仍然无法打印任何内容。在代码段和崩溃日志下面。
任何帮助都将受到高度赞赏。
#include <jni.h>
//#include <android/log.h>
#define APPNAME "handroid"
#define MAX(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define MIN(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
double* rgbData;
int rgbDataSize = 0;
JNIEXPORT
void
JNICALL
Java_handroid_classes_Camera_YUVtoRBGHSV(JNIEnv * env, jobject obj, jdoubleArray rgb_hsv, jbyteArray yuv420sp, jint width, jint height)
{
int sz;
int i;
int j;
int Y;
int Cr = 0;
int Cb = 0;
int pixPtr = 0;
int jDiv2 = 0;
int R = 0;
int G = 0;
int B = 0;
double tR = 0;
double tG = 0;
double tB = 0;
int cOff;
int w = width;
int h = height;
sz = w * h;
int pixel;
int uvp;
int y1192;
int y;
int v;
int u;
int yp;
//for hsv
double min, max, delta, hsv_h, hsv_s, hsv_v;
jboolean isCopy;
jbyte* yuv = (*env)->GetByteArrayElements(env, yuv420sp, &isCopy);
if(rgbDataSize < sz) {
double tmp[6];
rgbData = &tmp[0];
rgbDataSize = sz;
}
//Calculate pixel colors
for (j = 0, yp = 0; j < h; j++) {
uvp = sz + (j >> 1) * w, u = 0, v = 0;
for (i = 0; i < w; i++, yp++) {
y = (0xff & yuv[yp]) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv[uvp++]) - 128;
u = (0xff & yuv[uvp++]) - 128;
}
y1192 = 1192 * y;
R = (y1192 + 1634 * v);
G = (y1192 - 833 * v - 400 * u);
B = (y1192 + 2066 * u);
if (R < 0) R = 0;
else if (R > 262143) R = 262143;
if (G < 0) G = 0;
else if (G > 262143) G = 262143;
if (B < 0) B = 0;
else if (B > 262143) B = 262143;
pixel = 0xff000000 | ((R << 6) & 0xff0000) | ((G >> 2) & 0xff00) | ((B >> 10) & 0xff);
tR += (pixel >> 16) & 0xff;
tG += (pixel >> 8) & 0xff;
tB += (pixel >> 0) & 0xff;
}
}
//Create RGB sum (average pixel)
rgbData[0] = (double)(tR/255/sz);
rgbData[1] = (double)(tG/255/sz);
rgbData[2] = (double)(tB/255/sz);
//Calculate HSV
min = MIN(rgbData[0], MIN(rgbData[1], rgbData[2]));
max = MAX(rgbData[0], MAX(rgbData[1], rgbData[2]));
hsv_v = max;
delta = max - min;
if( max != 0 ){
hsv_s = delta / max;
if( rgbData[0] == max )
hsv_h = ( rgbData[1] - rgbData[2] ) / delta;
else if( rgbData[1] == max )
hsv_h=2+(rgbData[2]-rgbData[0])/delta;
else
hsv_h=4+(rgbData[0]-rgbData[1])/delta;
hsv_h *= 60;
if( hsv_h < 0 )
hsv_h += 360;
rgbData[3] = hsv_h;
rgbData[4] = hsv_s;
rgbData[5] = hsv_v;
}else {
// r = g = b = 0
hsv_s = 0;
hsv_h = -1;
rgbData[3] = hsv_h;
rgbData[4] = hsv_s;
rgbData[5] = hsv_v;
}
//Log the data in Android
//__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "The value R %f G %f B %f , H %f S %f V %f ", rgbData[0], rgbData[1], rgbData[2], rgbData[3], rgbData[4], rgbData[5]);
//Set RGB
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 1, ( jdouble * ) &rgbData[0] );
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 1, 1, ( jdouble * ) &rgbData[1] );
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 2, 1, ( jdouble * ) &rgbData[2] );
//Set HSV
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 3, 1, ( jdouble * ) &rgbData[3] );
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 4, 1, ( jdouble * ) &rgbData[4] );
(*env)->SetDoubleArrayRegion(env, rgb_hsv, 5, 1, ( jdouble * ) &rgbData[5] );
//Release the array data
//(*env)->ReleaseByteArrayElements(env, yuv420sp, yuv, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, yuv420sp, yuv, 0);
//(*env)->ReleaseDoubleArrayElements(env, yuv420sp, yuv,rgbData,min,max,0);
}
崩溃日志
04-03 15:30:27.687 5547-5547/com.hlib E/dalvikvm: VM aborting
04-03 15:30:27.687 5547-5547/com.hlib A/libc: Fatal signal 6 (SIGABRT) at 0x000015ab (code=-6), thread 5547 (it.hlib)
答案 0 :(得分:1)
我不熟悉Android下的Native C,但我会尝试:)
宏MIN&amp; MAX看起来非常奇特,不确定语法“({instr})”,它会被评估到最后一条指令吗?为什么不使用更传统的定义“MAX(a,b)((a)&gt;(b)?(a):( b))”?这将导致3次评估,而不是2次;但无论如何,MIN&amp; MAX以嵌套的方式在代码中使用,在这种情况下,使用普通函数可能更有效。
使用堆栈变量tmp [6]初始化rgbData,该变量将在if块结束后销毁,
if(rgbDataSize < sz) {
double tmp[6];
rgbData = &tmp[0];
rgbDataSize = sz;
}
的结果
jbyte* yuv = (*env)->GetByteArrayElements(env, yuv420sp, &isCopy);
应检查是否为null,它是否返回至少(w * h + w *(h / 2)+ w)字节的数组?通过以下方式访问:
v = (0xff & yuv[uvp++]) - 128;
u = (0xff & yuv[uvp++]) - 128;
关于位图“yuv”的大小,“width”和“height”参数是否正确?
块
if( max != 0 ){
将除以“delta”,可能为0.
下一个块是否需要“{}”才能包含这两个指令?
else
hsv_h=4+(rgbData[0]-rgbData[1])/delta;
hsv_h *= 60;
似乎6个函数调用只能用1个调用替换
<= (*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 1, ( jdouble * ) &rgbData[0] );
=> (*env)->SetDoubleArrayRegion(env, rgb_hsv, 0, 6, ( jdouble * ) &rgbData[0] );
这就是我能够简单地看出来的。