0

I try to display video on Android using Gstreamer like on other platforms:

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

But I think that winId() returns something else instead of ANativeWindow, because I get:

F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x5e in tid 3154 (gstglcontext)

So, how can I get instance of(or pointer to) ANativeWindow from some Qt widget on Android?

konstantin_doncov
  • 2,725
  • 4
  • 40
  • 100

2 Answers2

1

Support for embedding native widgets is incomplete and doesn't always work. Bear in mind that Qt may create native handles, but they do not necessarily represent actual native windows. Additionally, QWidget::winId() provides no effective guarantee of portability, only that the identifier is unique:

Portable in principle, but if you use it you are probably about to do something non-portable. Be careful.

The reason for this is that WId is actually a typedef for quintptr.

Solution: You will, at the very least, need to cast the return from winId to ANativeWindow, assuming this is the underlying window handle type that Qt uses to identify native windows.

This solution seems directed at X Windows but may provide some guidance.

Also see the documentation for QWidget::effectiveWinId() and QWidget::nativeParentWidget() for more helpful background information.

Update: Per the platform notes, there are quite a few caveats in using OpenGL + Qt + Android, including:

The platform plugin only supports full screen top-level OpenGL windows.

Community
  • 1
  • 1
jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
  • Thanks for the good and quick response! What you mean "cast the return from winId to ANativeWindow"? That means that I just need to `ANativeWindow *native_window = (ANativeWindow*) this->ui->playback_widget->winId()`? Ok, and what I should to do next with this handler? And what about WA_NativeWindow? I tried to use `this->ui->playback_widget->setAttribute(Qt::WA_NativeWindow)` but unfortunately this changes nothing. – konstantin_doncov May 02 '16 at 17:40
  • "That means that I just need to ANativeWindow *native_window = (ANativeWindow*) this->ui->playback_widget->winId()?" That's just the start. Check the other question I linked to for – jonspaceharper May 02 '16 at 18:09
  • Understood, thanks. And which header I need to include? Because my instance of `ANativeWindow` has no members. Also, I don't know what I should do next. – konstantin_doncov May 02 '16 at 18:14
  • Sorry, got cut off. I'm not an Android developer; I've just done a fair amount with non-portable `winId()` calls. Look up `ANativeWidget`'s documentation for the header to include. – jonspaceharper May 02 '16 at 18:18
  • Do what you would normally do: try it. Run it through the debugger. Read more documentation. Mull it over. Search for similar issues. All the usual "I'm stuck" things programmers do. :-) – jonspaceharper May 02 '16 at 18:24
  • Yes, I know :) I asked it because I didn't found any info about that. Anyway I tried to use `ANativeWindow native_window = (ANativeWindow) this->ui->playback_widget->winId()` and it's doesn't changes anything. I also tried to do this with the main window(`(ANativeWindow*) this->winId()`) but this changes nothing too. Maybe you have some other ideas or notes? – konstantin_doncov May 02 '16 at 18:43
  • Is `playback_widget` a Qt widget or native widget? You might update your question with more code to flesh it out. People bite on questions with details. – jonspaceharper May 02 '16 at 18:53
  • playback_widget - QOpenGLWidget, but as I said in the previous comment I also tried to do this with the main window, but nothing changes(strange). Maybe I can somehow use native widgets/windows? P.S. I will change question description... – konstantin_doncov May 02 '16 at 18:59
  • You're going to have some trouble getting this to work, unfortunately. I updated my answer with some additional nuggets to get you in the right direction. Did I at least answer your original question? – jonspaceharper May 03 '16 at 16:44
0

After the answer of @don-prog and some reading time I could make it work. Here is my code. Just a note: I have to delay this code execution until Qt finished loading views and layouts.

The following code retrieves the QtActivity Java object, then it dives into views and layout objects up to the QtSurface - which extends android.view.SurfaceView. Then it ask for the SurfaceHolder to finally get the Surface object that we need to call ANativeWindow_fromSurface.

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";
        }
    }

Hope it helps anybody else

gabocalero
  • 473
  • 6
  • 15