java - 在 Android 上使用 opengles 播放 YUV 视频后 Activity 困惑

标签 java android c++ opengl-es

我用opengl es配合jni播放YUV视频,视频没问题。

但是当我关闭 GLSurfaceView 并返回主 Activity 时。

主要Activity中显示的字符和图像变得困惑。

所有图标变为黑色实心矩形。所有字符变为白色实心矩形。

代码看起来像是来自 WebRTC 并由其他人修改。 我是一名 C 程序员,不熟悉 OpenGl。所以解决这个问题对我来说真的是个大问题。

我在 JNI 中创建句柄是这样的:

bool isAttached = false;
JNIEnv* env = NULL;
if (_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    // try to attach the thread and get the env
    // Attach this thread to JVM
    jint res = _jvm->AttachCurrentThread(&env, NULL);

    // Get the JNI env for this thread
    if ((res < 0) || !env) {
        LOGE("%s: Could not attach thread to JVM (%d, %p)",
                __FUNCTION__, res, env);
        return -1;
    }
    isAttached = true;
}

// get the ViEAndroidGLES20 class
jclass javaRenderClassLocal = reinterpret_cast<jclass> (env->FindClass("com/wg/rgc/library/gl/ViEAndroidGLES20"));
if (!javaRenderClassLocal) {
    LOGE("%s: could not find ViEAndroidGLES20", __FUNCTION__);
    return -1;
}

_javaRenderClass = reinterpret_cast<jclass> (env->NewGlobalRef(javaRenderClassLocal));
if (!_javaRenderClass) {
    LOGE("%s: could not create Java SurfaceHolder class reference",
            __FUNCTION__);
    return -1;
}

// Delete local class ref, we only use the global ref
env->DeleteLocalRef(javaRenderClassLocal);
jmethodID cidUseOpenGL = env->GetStaticMethodID(_javaRenderClass,
        "UseOpenGL2",
        "(Ljava/lang/Object;)Z");
if (cidUseOpenGL == NULL) {
    LOGE("%s: could not get UseOpenGL ID", __FUNCTION__);
    return false;
}
jboolean res = env->CallStaticBooleanMethod(_javaRenderClass,
        cidUseOpenGL, (jobject) _ptrWindow);

// create a reference to the object (to tell JNI that we are referencing it
// after this function has returned)
_javaRenderObj = reinterpret_cast<jobject> (env->NewGlobalRef((jobject)_ptrWindow));
if (!_javaRenderObj)
{
    LOGE("%s: could not create Java SurfaceRender object reference",
            __FUNCTION__);
    return -1;
}

// get the method ID for the ReDraw function
_redrawCid = env->GetMethodID(_javaRenderClass, "ReDraw", "()V");
if (_redrawCid == NULL) {
    LOGE("%s: could not get ReDraw ID", __FUNCTION__);
    return -1;
}

_registerNativeCID = env->GetMethodID(_javaRenderClass,
        "RegisterNativeObject", "(J)V");
if (_registerNativeCID == NULL) {
    LOGE("%s: could not get RegisterNativeObject ID", __FUNCTION__);
    return -1;
}

_deRegisterNativeCID = env->GetMethodID(_javaRenderClass,
        "DeRegisterNativeObject", "()V");
if (_deRegisterNativeCID == NULL) {
    LOGE("%s: could not get DeRegisterNativeObject ID",
            __FUNCTION__);
    return -1;
}

JNINativeMethod nativeFunctions[2] = {
    { "DrawNative",
        "(J)V",
        (void*) &AndroidNativeOpenGl2Channel::DrawNativeStatic, },
    { "CreateOpenGLNative",
        "(JII)I",
        (void*) &AndroidNativeOpenGl2Channel::CreateOpenGLNativeStatic },
};
if (env->RegisterNatives(_javaRenderClass, nativeFunctions, 2) == 0) {
    LOGE("%s: Registered native functions", __FUNCTION__);
}
else {
    LOGE("%s: Failed to register native functions", __FUNCTION__);
    return -1;
}

env->CallVoidMethod(_javaRenderObj, _registerNativeCID, (jlong) this);

if (isAttached) {
    if (_jvm->DetachCurrentThread() < 0) {
        LOGE("%s: Could not detach thread from JVM", __FUNCTION__);
    }
}

LOGE("%s done", __FUNCTION__);

if (_openGLRenderer.SetCoordinates(0, 1.0, 1.0, 0, 0) != 0) {
    return -1;
}

isAlreadyInit = 1;  //Init finish
return 0;

然后我像这样在 JNI 中关闭这个句柄:

bool isAttached = false;
JNIEnv* env = NULL;
if (_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
    // try to attach the thread and get the env
    // Attach this thread to JVM
    jint res = _jvm->AttachCurrentThread(&env, NULL);

    // Get the JNI env for this thread
    if ((res < 0) || !env) {
        LOGE("%s: Could not attach thread to JVM (%d, %p)",
                __FUNCTION__, res, env);
        env = NULL;
    } else {
        isAttached = true;
    }
}

if (env && _deRegisterNativeCID) {
    env->CallVoidMethod(_javaRenderObj, _deRegisterNativeCID);
}

env->DeleteGlobalRef(_javaRenderObj);
env->DeleteGlobalRef(_javaRenderClass);

if (isAttached) {
    if (_jvm->DetachCurrentThread() < 0) {
        LOGE("%s: Could not detach thread from JVM",
                __FUNCTION__);
    }
}

方法 env->CallVoidMethod(_javaRenderObj, _deRegisterNativeCID);在 Java src 中调用 Java 方法:

nativeFunctionLock.lock();
nativeFunctionsRegisted = false;
openGLCreated = false;
this.nativeObject = 0;
nativeFunctionLock.unlock();

Java src 中的代码看起来像是扩展了 GLSurfaceView 并实现了 GLSurfaceView.Renderer。在 JNI 中,代码将一些方法注册为 Java 中的 native 方法。 代码对我来说很复杂,但我的老板要求我尽快解决这个问题。 想不通为什么播放YUV视频后,每一个图像和字符都变成了矩形。这是怎么发生的?

最佳答案

你可能在渲染后删除了纹理,你可以尝试保留它们,并在应用程序终止时释放它们

关于java - 在 Android 上使用 opengles 播放 YUV 视频后 Activity 困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29944457/

相关文章:

c# - 用于对具有任意属性的网络设备进行建模以供学习的最佳 API?

java - 如何使用 Java 泛型来避免覆盖继承的方法(类似模板的行为)?

使用 TagSoup 解析页面 URL 以创建 DOM 时出现 java IOException

iphone - 电池时间计算

c++ - 将数组数据插入 vector 时不保存

Java JTextArea 字体

android - 应用程序启动时看到的是白屏和操作栏,而不是黑屏

android - 在 Android SDK 上导入 .ics 文件并添加到日历

c++ - 传递给存储常量引用的成员的临时对象的生命周期

c++ - 在 C 中改变 const 值