【发布时间】:2020-03-11 12:48:06
【问题描述】:
TL;DR;我在通过线程将 FFMPEG 原始数据从 C++ 代码传递到 JAVA 代码以进行显示时遇到问题。
有一个服务器设置向其客户端发送编码帧。这些编码帧是用一些 FFMPEG 魔法编码的。在客户端收到时,上述帧将被解码为原始 RGB 数据(作为无符号字符 *)。现在的问题是帧是在某种“侦听器”中接收的。只是一个在后台运行的线程轮询服务器并在新帧可用时运行特定的onFrame 函数。
当前以视频格式显示帧的解决方案是将每个帧保存到 C++ 的内部存储中,然后在 java 端有一个FileObserver,一旦图像写入内存就会显示图像。遗憾的是,这种方法在手机上生成了 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);
之后,我在我的onFrame 中调用jvm->AttachCurrentThread(&m_globalEnv, NULL);
然后我尝试从代码内部的某个地方调用一个 JAVA 方法(这与我在 onFrame 中调用它的位置/时间无关):
m_globalEnv->CallVoidMethod(m_globalObject, "testMethod", 5);
然后所有崩溃:
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
.
.
.
编辑 1
在尝试了 Michael 解决方案中的代码后,我收到了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 中被调试器突出显示的代码行位于 void CallVoidMethod(jobject obj, jmethodID methodID, ...)
它是
functions->CallVoidMethodV(this, obj, methodID, args);
在第 228 行定义:
void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
【问题讨论】:
-
m_globalEnv的意义何在?您不能跨线程共享JNIEnv*,那么为什么它需要是全局的? -
不管怎样,你说你正在调用
AttachCurrentThread,但是日志说线程没有附加。因此,您可能在代码的某些部分中存在未向我们展示的错误。 -
@Michael 由于我无法在
onFrame中传递JNIEnv*。所以我做了一个全局参考,以后每次收到时都会调用它。我还尝试通过获取对全局的引用,为每一帧在线程中创建一个新的 Env。我可能在这里采取了错误的方法,而不是否认这一点。 -
也许stackoverflow.com/questions/30026030/… 可以提供帮助。
-
thiz可能是一个陈旧的本地引用。您应该在分配m_globalObject时使用NewGlobalRef将其设为全局引用,然后在本机代码中不再需要该对象时使用DeleteGlobalRef释放它。
标签: java android c++ ffmpeg java-native-interface