简体   繁体   English

Android上的gstreamer:当unfing管道时异常?

[英]gstreamer on Android: exception when unrefing pipeline?

I have a very strange problem in my App. 我的应用程序中有一个非常奇怪的问题。 The plan is to use gstreamer to play a videostream and display it on a SurfaceView. 计划是使用gstreamer播放视频流并将其显示在SurfaceView上。 The pipeline uses glimagesink to display the video. 管道使用glimagesink来显示视频。

When my activity terminates it calls release_pipeline (set pipeline state to GST_STATE_NULL, unref it, set my reference to NULL). 当我的活动终止时,它调用release_pipeline (将管道状态设置为GST_STATE_NULL,取消它,将我的引用设置为NULL)。 The unrefing results in this error and I have no idea what causes it: 这个错误导致了这个错误,我不知道是什么导致它:

 validate_display:211 error 3001 (EGL_NOT_INITIALIZED)

followed by a segfault. 然后是段错误。 The application actually crashes in Android's Choreographer but I don't know where to go from there. 该应用程序实际上在Android的Choreographer中崩溃,但我不知道从那里去哪里。

The SurfaceView lives inside a Fragment and has a Callback which calls surface_release in surfaceDestroyed and calls surface_update in surfaceChanged . 该SurfaceView生活片段内并具有调用回调surface_releasesurfaceDestroyed并调用surface_updatesurfaceChanged The callback is added in onCreateView . 回调是在onCreateView添加的。 My Objects are kept in an extern struct called jnictx. 我的对象保存在一个名为jnictx的extern结构中。 These functions are defined as: 这些功能定义为:

 void surface_release()
{
    if (jnictx->gst.pipeline != NULL)
    {
        GstElement* vsink = gst_bin_get_by_name(jnictx->gst.pipeline, "vr_sink");
        gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (guintptr) NULL);
        gst_element_set_state(GST_ELEMENT(jnictx->gst.pipeline), GST_STATE_READY);
        gst_object_unref(vsink);
    }

    if (jnictx->gst.surface_win != NULL)
    {
        ANativeWindow_release(jnictx->gst.surface_win);
        jnictx->gst.surface_win = NULL;
    }
}

void surface_update(JNIEnv* env, jobject surface)
{
    ANativeWindow *new_window = ANativeWindow_fromSurface(env, surface);

    if (jnictx->gst.surface_win != NULL)
    {
        // Release the old reference
        ANativeWindow_release(jnictx->gst.surface_win);

        // The window did not change, just update the surface
        if (jnictx->gst.surface_win == new_window)
        {
            if (jnictx->gst.pipeline != NULL)
            {
                GstElement* vsink = gst_bin_get_by_name(jnictx->gst.pipeline, "vr_sink");

                // Supposedly we have to call this twice so the surface updates with the new values
                gst_video_overlay_expose(GST_VIDEO_OVERLAY(vsink));
                gst_video_overlay_expose(GST_VIDEO_OVERLAY(vsink));

                gst_object_unref(vsink);
            }

            // The window did not change, by unreffing it above we unreffed the
            // reference we acquired with ANativeWindow_fromSurface as well
            return;
        }
    }


    // If we reach this point the window changed and we have to set the new handle
    if (jnictx->gst.pipeline != NULL)
    {
        GstElement* vsink = gst_bin_get_by_name(jnictx->gst.pipeline, "vr_sink");

        jnictx->gst.surface_win = new_window;
        gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (guintptr) new_window);

        gst_object_unref(vsink);
    }
}

The code for setting up the glimagesink comes from the example found here . 设置glimagesink的代码来自此处的示例。 I should add that the pipeline is not referenced elsewhere nor do I access it anywhere without checking whether it's NULL. 我应该补充说,管道在其他地方没有被引用,也没有在任何地方访问它而不检查它是否为NULL。

I'm not sure if this is relevant but gstreamer lives inside it's own thread which uses a GMainLoop . 我不确定这是否相关,但是gstreamer存在于使用GMainLoop的自己的线程中。 The pipeline is created inside this thread and released when the GMainLoop is quit. 管道在此线程内创建,并在GMainLoop退出时释放。 I head that GLES and threads on Android are... tricky, so maybe...? 我认为GLES和Android上的线程都很棘手,所以也许......?

Anyway, if someone can help I'd be really grateful! 无论如何,如果有人可以帮助,我会非常感激! If you need more code just let me know. 如果您需要更多代码,请告诉我。

My pipeline used queues (with leaky=downstream) in the wrong places which somehow prevented the pipeline from entering PAUSED state (some elements where still in READY). 我的管道在错误的地方使用队列(泄漏=下游),以某种方式阻止管道进入PAUSED状态(某些元素仍处于READY状态)。 Freeing the pipeline probably caused an illegal pointer access (maybe on the message bus listener) which caused said exception. 释放管道可能导致非法指针访问(可能在消息总线侦听器上),这导致了所述异常。

Visualizing the pipeline using GST_DEBUG_BIN_TO_DOT_FILE() helped to identify the issue (see this link ). 使用GST_DEBUG_BIN_TO_DOT_FILE()可视化管道有助于识别问题(请参阅此链接 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM