从Qt小部件获取ANativeWindow

时间:2016-05-02 12:53:19

标签: android qt gstreamer

我尝试在其他平台上使用Gstreamer在Android上显示视频:

gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink), this->ui->playback_widget->winId()); 
//playback_widget - QOpenGLWidget

但我认为winId()会返回其他东西而不是ANativeWindow,因为我得到了:

  

F libc:致命信号11(SIGSEGV),代码1,故障地址0x5e in tid   3154(gstglcontext)

那么,如何从Android上的某些Qt小部件获取ANativeWindow的实例(或指针)?

2 个答案:

答案 0 :(得分:0)

支持嵌入本机小部件是不完整的,并不总是有效。请记住,Qt可能会创建本机句柄,但它们不一定代表实际的本机窗口。此外,QWidget::winId()没有提供可移植性的有效保证,只是标识符是唯一的:

  

原则上是便携式的,但是如果你使用它,你可能会做一些不便携的事情。小心。

原因是WId实际上是typedef的{​​{1}}。

解决方案:您至少需要将quintptr的回复转换为winId,假设这是基础窗口句柄类型, Qt用于识别本机窗口

This solution似乎针对的是X Windows,但可能会提供一些指导。

另请参阅QWidget::effectiveWinId()QWidget::nativeParentWidget()的文档以获取更多有用的背景信息。

更新Per the platform notes,使用OpenGL + Qt + Android时有一些注意事项,包括:

  

平台插件仅支持全屏顶级OpenGL窗口。

答案 1 :(得分:0)

在@ don-prog的答案和一些阅读时间后,我可以使它工作。这是我的代码。请注意:我必须延迟此代码执行,直到Qt完成加载视图和布局。

以下代码检索QtActivity Java对象,然后深入查看视图和布局对象,直到QtSurface - 扩展了android.view.SurfaceView。然后它要求SurfaceHolder最终得到我们需要调用ANativeWindow_fromSurface的Surface对象。

QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
    jobject activity = (jobject)nativeInterface->nativeResourceForIntegration("QtActivity");
    QAndroidJniEnvironment * qjniEnv;
    JNIEnv * jniEnv;
    JavaVM * jvm = qjniEnv->javaVM();
    jvm->GetEnv(reinterpret_cast<void**>(&qjniEnv), JNI_VERSION_1_6);
    jvm->AttachCurrentThread(&jniEnv,NULL);


    jint r_id_content = QAndroidJniObject::getStaticField<jint>("android/R$id", "content");


    QAndroidJniObject view = ((QAndroidJniObject) activity).callObjectMethod("findViewById", "(I)Landroid/view/View;", r_id_content);
    if (view.isValid()) {
        QAndroidJniObject child1 = view.callObjectMethod("getChildAt", "(I)Landroid/view/View;", 0);
        QAndroidJniObject child2 = child1.callObjectMethod("getChildAt", "(I)Landroid/view/View;", 0);
        if (child2.isValid()) {
            QAndroidJniObject sHolder = child2.callObjectMethod("getHolder","()Landroid/view/SurfaceHolder;");
            if (sHolder.isValid()) {
                QAndroidJniObject theSurface = sHolder.callObjectMethod("getSurface","()Landroid/view/Surface;");
                if (theSurface.isValid()) {
                    ANativeWindow* awindow = ANativeWindow_fromSurface(jniEnv, theSurface.object());
                    qDebug() << "This is a ANativeWindow " << awindow;
                }
            }
        } else {
            qDebug() << "Views are not loaded yet or you are not in the Qt UI Thread";
        }
    }

希望它可以帮助其他人