Fal*_*uun 6 c++ java java-native-interface android ffmpeg
TL;博士; 我在通过线程将 FFMPEG 原始数据从 C++ 代码传递到 JAVA 代码以进行显示时遇到问题。
有一个服务器将编码帧发送到其客户端。这些编码帧是用一些 FFMPEG 魔法进行编码的。当在客户端接收时,上述帧被解码为原始 RGB 数据(作为 unsigned char *)。现在的问题是帧是在某种“侦听器”中接收的。只是一个在后台运行的线程,轮询服务器并onFrame在新帧可用时运行特定功能。
当前以视频格式显示帧的解决方案是将每个帧保存到 C++ 的内部存储中,然后在FileObserverjava 端在图像写入内存后立即显示图像。遗憾的是,这种方法在手机上生成 6 FPS 视频,而在服务器上生成 10 FPS 视频。
我需要一种将 unsigned char * (jbytearray) 传递给我的 JAVA 代码的方法,这样我就可以解码它并从 RAM 而不是磁盘显示它。
值得一提的是,onFrame函数的参数列表中不能有JNIEnv*&& jobject(库要求)。
到目前为止,我所尝试的是在我的MainActivity方法中创建一个本机方法,通过JNIEnv该jobject方法将它们传递给全局变量
JNIEnv* m_globalEnv = env;
jobject m_globalObject = thiz;
JavaVM m_jvm = 0;
jclass mainActivity = m_globalEnv->GetObjectClass(m_globalObject);
jmethodID testMethod = m_globalEnv->GetMethodID(mainClass, "testMethod", "(I)V");
m_globalEnv->GetJavaVM(&m_jvm);
Run Code Online (Sandbox Code Playgroud)
之后,在我的onFrameI 调用中
jvm->AttachCurrentThread(&m_globalEnv, NULL);
,然后我尝试从代码内部的某个位置调用 JAVA 方法(与onFrameI 调用它的位置/时间无关):
m_globalEnv->CallVoidMethod(m_globalObject, "testMethod", 5);
Run Code Online (Sandbox Code Playgroud)
然后所有崩溃都会发生:
1- JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xffe8ea7c
2- JNI DETECTED ERROR IN APPLICATION: Thread is making JNI calls without being attached
.
.
.
Run Code Online (Sandbox Code Playgroud)
尝试了迈克尔解决方案中的代码后,我收到了错误
java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc94f7f8c。在调试模式下运行应用程序以捕获错误后,我到达了jni.h; 触发错误的代码行是:
m_env->CallVoidMethod(m_globalObject, testMethod, 5);
(5 是我出于测试目的而尝试传递的数字)。jni.h 中调试器突出显示的代码行位于
第 228 行中定义的
void CallVoidMethod(jobject obj, jmethodID methodID, ...)
代码行
:functions->CallVoidMethodV(this, obj, methodID, args);void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
我发现代码有两个潜在问题:
JNIEnv*1.跨线程共享
每个本机线程都应该通过将自身附加到 JVM 来获得自己的线程JNIEnv*,然后在某个时刻分离自己。有关更多详细信息和可能的解决方案,请参阅此答案。
2. 缓存本地引用作为本机函数的第二个参数收到的引用是本地引用,调用 JNI 函数返回的大多数引用也是本地
引用。
本地引用只能“从它最初传递到的线程中使用,并且在显式调用 DeleteLocalRef() 或更常见的情况下,直到从本机方法返回之前一直有效”。thizjobject
如果您想从另一个线程使用该对象,您需要从本地引用创建全局引用:
m_globalObject = NewGlobalRef(thiz);
Run Code Online (Sandbox Code Playgroud)
DeleteGlobalRef(m_globalObject)当您不再需要在本机代码中的任何位置使用该对象时,请记住删除全局引用 ( )。否则可能会导致内存泄漏。
| 归档时间: |
|
| 查看次数: |
2650 次 |
| 最近记录: |