Jni编程会用到的工具函数,做积累
1. 打开文件路径,返回文件描述符给Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//打开路径文件,并抬FileDescriptor
jobject openFile(JNIEnv *env, jstring path, jint flags){
int
fd;
jobject mFileDescriptor;
/* Opening device */
{
jboolean iscopy;
const
char
*path_utf = env->GetStringUTFChars(path, &iscopy);
fd = open(path_utf, O_RDWR | flags);
env->ReleaseStringUTFChars(path, path_utf);
if
(fd == -1)
{
/* Throw an exception */
LOGE(
"Cannot open port"
);
return
NULL;
}
}
/* Create a corresponding file descriptor */
{
jclass cFileDescriptor = env->FindClass(
"java/io/FileDescriptor"
);
jmethodID iFileDescriptor = env->GetMethodID(cFileDescriptor,
"<init>"
,
"()V"
);
jfieldID descriptorID = env->GetFieldID(cFileDescriptor,
"descriptor"
,
"I"
);
mFileDescriptor = env->NewObject(cFileDescriptor, iFileDescriptor);
env->SetIntField(mFileDescriptor, descriptorID, (jint)fd);
}
return
mFileDescriptor;
}
|
2. Char转换成String
1
2
3
4
5
6
7
8
9
10
11
|
//char * to string
jstring charToString(JNIEnv *env,
const
char
*chr){
LOGI(
"charToString: %s\n"
, chr);
jclass strClass = env->FindClass(
"java/lang/String"
);
jmethodID strConstruct = env->GetMethodID(strClass,
"<init>"
,
"([BLjava/lang/String;)V"
);
jbyteArray bytes = env->NewByteArray(
strlen
(chr));
env->SetByteArrayRegion(bytes, 0,
strlen
(chr), (jbyte*)chr);
jstring encoding = env->NewStringUTF(
"utf-8"
);
return
(jstring)env->NewObject(strClass, strConstruct, bytes, encoding);
}
|
3. String转换为Char
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//jstring to char*
char
* jstringToChar(JNIEnv* env, jstring jstr)
{
char
* rtn = NULL;
jclass clsstring = env->FindClass(
"java/lang/String"
);
jstring strencode = env->NewStringUTF(
"utf-8"
);
jmethodID mid = env->GetMethodID(clsstring,
"getBytes"
,
"(Ljava/lang/String;)[B"
);
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if
(alen > 0)
{
rtn = (
char
*)
malloc
(alen + 1);
memcpy
(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return
rtn;
}
|
4. 上层传一个ByteBuffer给Jni用
Java:
private ByteBuffer mImageBuffer;
mImageBuffer = ByteBuffer.allocateDirect(mImageBufferSize);
ret = setDirectBuffer(mImageBuffer, mImageBufferSize);
Jni:
jint Java_com_camera_simplewebcam_CameraPreview_setDirectBuffer(JNIEnv *env, jobject thiz,
jobject jbuf, jint jlen) {
char *pImageBuf = NULL;
//获取Buffer首地址
pImageBuf = (char *)(*env)->GetDirectBufferAddress(env, jbuf);
if (NULL == pImageBuf) {
LOGE("Failed to get direct buffer");
return -1;
}
return 0;
}
5. 色彩Buffer转换成Bitmap类。
在UVC中把一帧的buffer转换成上层需要显示的Bitmap。Android.mk里要加入库LOCAL_LDLIBS := -ljnigraphics
void
Java_com_camera_simplewebcam_CameraPreview_pixeltobmp( JNIEnv* env,jobject thiz,jobject bitmap){
jboolean bo;
AndroidBitmapInfo info;
void* pixels;
int ret;
int i;
int *colors;
int width=0;
int height=0;
//提取bmp信息
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return;
}
width = info.width;
height = info.height;
if(!rgb || !ybuf) return;
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888 !");
return;
}
//bitmap提取buf
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
}
colors = (int*)pixels;
int *lrgb =NULL;
lrgb = &rgb[0];
//把目录buf拷贝到bitmap的buffer里
for(i=0 ; i<width*height ; i++){
*colors++ = *lrgb++;
}
AndroidBitmap_unlockPixels(env, bitmap);
}