2015-02-24 56 views
0

我的应用程序中有一个很奇怪的问题。计划是使用gstreamer播放一个视频流并将其显示在SurfaceView上。管道使用glimagesink来显示视频。Android上的gstreamer:重新启动管道时发生异常?

当我的活动终止时,它调用release_pipeline(将管道状态设置为GST_STATE_NULL,取消它,将我的引用设置为NULL)。在这个错误unrefing结果,我不知道是什么导致它:

validate_display:211 error 3001 (EGL_NOT_INITIALIZED) 

后跟一个段错误。该应用程序实际上在Android的编排器中崩溃,但我不知道该从哪里去。

的SurfaceView生活片段内并具有在surfaceDestroyed调用surface_release,并呼吁在surfaceChangedsurface_update一个回调。该回调加入onCreateView。 我的对象保存在名为jnictx的extern结构中。这些函数被定义为:

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

用于设置glimagesink的代码来自例如发现here。我应该补充说,管道没有在别处被引用,我也不会在任何地方访问它,而不检查它是否为NULL。

我不确定这是否相关,但gstreamer住在它自己的线程中,它使用GMainLoop。管道在该线程内部创建,并在GMainLoop退出时释放。我认为GLES和Android上的线程很棘手,所以也许......?

无论如何,如果有人可以帮助,我会很感激!如果你需要更多的代码,请让我知道。

回答

0

我的管道在错误的地方使用了队列(leaky = downstream),这些地方阻碍了管道进入PAUSED状态(一些仍处于READY状态的元素)。释放管道可能会导致非法指针访问(可能在消息总线侦听器上),从而导致异常。

使用GST_DEBUG_BIN_TO_DOT_FILE()可视化管线有助于确定问题(请参阅this link)。

相关问题