android jni中将大数据回调到java层的时候用法,比如视频流,音频流等,图片流等 比如我用ffmpeg解码好视频流,想送到java层使用opengGL进行显示,opencv进行人脸识别等等
java层
//将解码好后的视频流回调回来
public void CallBack_VideoDecodeData(Object object, int len) {
//这里强制转换为ByteBuffer即可
ByteBuffer buffer = (ByteBuffer) object;
if (videoDecodeSteamCallBack != null) {
videoDecodeSteamCallBack.onVideoDecodeData(buffer, len);
}
}
jni层
g_CallBack_VideoDecodeData = (*env)->GetMethodID(env,clazz, "CallBack_VideoDecodeData", "(Ljava/lang/Object;I)V");
/**
* 直播的时候视频回调,这个是解码好后的视频
*/
int RT_VideoDecodeDataCallBack(uint8_t *data,int len){
JNIEnv *env;
int cRet= RT_GetEnv(&env);
if(cRet==-1){
return 0;
}
if(g_CallBack_VideoDecodeData == NULL){
LOGE("[%s:%d]g_CallBack_VideoDecodeData=NULL!\n",__FUNCTION__,__LINE__);
return 0;
}
#if 0
/*
使用这种方式,效率很低,并且内存抖动非常大
*/
jbyteArray bytes = 0;
bytes = (*env)->NewByteArray(env, len);
if (bytes != NULL) {
(*env)->SetByteArrayRegion(env, bytes, 0, len,(jbyte *)data);
}
(*env)->CallVoidMethod(env,g_callBackHandle.callBackObj,g_CallBack_VideoDecodeData,bytes,len);
(*env)->DeleteLocalRef (env,bytes);
#else
/*
使用这种方式回调回去,效率会高很多,少了内存的拷贝,使用上面这种方式是要经过内存拷贝的
*/
jobject _buf = (jobject)0;
_buf = (*env)->NewDirectByteBuffer(env,data,len);
(*env)->CallVoidMethod(env,g_callBackHandle.callBackObj,g_CallBack_VideoDecodeData,_buf ,len);
(*env)->DeleteLocalRef (env,_buf);
#endif
//如果是绑定的方式,要解绑
if(cRet){
(*g_callBackHandle.javaVM)->DetachCurrentThread(g_callBackHandle.javaVM);
}
return 0;
}
android openGL glMapBufferRange源码也是这样用的
// C function GLvoid * glMapBufferRange ( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access )
public static native java.nio.Buffer glMapBufferRange(
int target,
int offset,
int length,
int access
);
对应的jni层
/* GLvoid * glMapBufferRange ( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access ) */
static jobject
android_glMapBufferRange__IIII
(JNIEnv *_env, jobject _this, jint target, jint offset, jint length, jint access) {
GLvoid* _p = glMapBufferRange((GLenum)target,
(GLintptr)offset, (GLsizeiptr)length, (GLbitfield)access);
jobject _buf = (jobject)0;
if (_p) {
_buf = _env->NewDirectByteBuffer(_p, length);
}
return _buf;
}
唯一区别 的是它不需要手动的释放,因为它是以返回值的方式返回,会由java虚拟机自动回收,如果像我这样的写的话,必须要调用(*env)->DeleteLocalRef (env,_buf);要不很快就会
A/art: art/runtime/indirect_reference_table.cc:115] JNI ERROR (app bug): local reference table overflow (max=512)
A/art: art/runtime/indirect_reference_table.cc:115] local reference table dump:
A/art: art/runtime/indirect_reference_table.cc:115] Last 10 entries (of 512):
A/art: art/runtime/indirect_reference_table.cc:115] 511: 0x12e09500 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 510: 0x12e094c0 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 509: 0x12e09480 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 508: 0x12e09440 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 507: 0x12e09400 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 506: 0x12e093c0 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 505: 0x12e09380 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 504: 0x12e09340 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 503: 0x12e09300 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] 502: 0x12e092c0 java.nio.DirectByteBuffer
A/art: art/runtime/indirect_reference_table.cc:115] Summary:
A/art: art/runtime/indirect_reference_table.cc:115] 512 of java.nio.DirectByteBuffer (512 unique instances)