从暂停到播放时 Gstreamer 管道失败?

Posted

技术标签:

【中文标题】从暂停到播放时 Gstreamer 管道失败?【英文标题】:Gstreamer pipeline failing when going from PAUSED TO PLAYING? 【发布时间】:2021-09-14 18:07:41 【问题描述】:

首先,我运行以下命令将我的所有管道元素设置为暂停:int ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);

接下来,我检查所有管道组件以确保它们处于暂停状态(它们是):

GstElement(imagesaver), status = PAUSED, pending = VOID_PENDING
GstElement(saveImageTee), status = PAUSED, pending = VOID_PENDING
GstElement(imagevideoconvert), status = PAUSED, pending = VOID_PENDING
GstElement(imagecapsfilter), status = PAUSED, pending = VOID_PENDING
GstElement(imagevideocrop), status = PAUSED, pending = VOID_PENDING
GstElement(videomuxer), status = PAUSED, pending = VOID_PENDING
GstElement(h264encoder), status = PAUSED, pending = VOID_PENDING
GstElement(imagequeue), status = PAUSED, pending = VOID_PENDING
GstElement(featurescanner), status = PAUSED, pending = PAUSED
GstElement(scannerqueue), status = PAUSED, pending = VOID_PENDING
GstElement(cfilter), status = PAUSED, pending = VOID_PENDING
GstElement(videoconversion), status = PAUSED, pending = VOID_PENDING
GstElement(convertqueue), status = PAUSED, pending = VOID_PENDING
GstElement(crop), status = PAUSED, pending = VOID_PENDING
GstElement(cropQueue), status = PAUSED, pending = VOID_PENDING
GstElement(source), status = PAUSED, pending = VOID_PENDING

然后我尝试播放我的管道: int ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);

这导致我的所有元素都设置为NULL 状态

GstElement(imagesaver), status = NULL, pending = VOID_PENDING
GstElement(saveImageTee), status = NULL, pending = VOID_PENDING
GstElement(imagevideoconvert), status = NULL, pending = VOID_PENDING
GstElement(imagecapsfilter), status = NULL, pending = VOID_PENDING
GstElement(imagevideocrop), status = NULL, pending = VOID_PENDING
GstElement(videomuxer), status = NULL, pending = VOID_PENDING
GstElement(h264encoder), status = NULL, pending = VOID_PENDING
GstElement(imagequeue), status = NULL, pending = VOID_PENDING
GstElement(featurescanner), status = NULL, pending = VOID_PENDING
GstElement(scannerqueue), status = NULL, pending = VOID_PENDING
GstElement(cfilter), status = NULL, pending = VOID_PENDING
GstElement(videoconversion), status = NULL, pending = VOID_PENDING
GstElement(convertqueue), status = NULL, pending = VOID_PENDING
GstElement(crop), status = NULL, pending = VOID_PENDING
GstElement(cropQueue), status = NULL, pending = VOID_PENDING
GstElement(source), status = NULL, pending = VOID_PENDING

我得到这个输出的错误信息是:

Setting pipeline to Play state
Pipeline would not play, returned 2

返回值 2 是:GST_STATE_CHANGE_ASYNC,我认为可以通过将 fileSink 异步属性设置为 false 来修复它: g_object_set(G_OBJECT (fileSink), "async", gboolean(FALSE), NULL);

这是我在暂停状态后调用来播放管道的函数:

void ScanningProcessor::PlayPipeline()

    gst_element_set_state(GST_ELEMENT(fileSink), GST_STATE_PLAYING);
    if(GST_STATE(pipeline) != GST_STATE_NULL)
    
        MBPLog::Log(LM_CameraLibrary, LS_Informational, "Setting pipeline to Play state");
        int ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
        if(ret != GST_STATE_PLAYING) 
        
            MBPLog::Log(LM_CameraLibrary, LS_Error, "Pipeline would not play, returned %d", ret);
            gst_element_set_state (pipeline, GST_STATE_NULL);
        
     

【问题讨论】:

这可能需要一些调试才能看到根本情况。如果您提供Minimal, Reproducible Example 以便人们可以提供帮助,将会有所帮助。 if(GST_STATE(pipeline) != GST_STATE_NULL) - 您的代码不会抛出异常或弹出错误。放入一些显示错误的代码。 @moi 我的代码总是进入那部分代码,因为管道处于暂停状态。然后,当我播放管道时,我得到一个返回值 1,这意味着成功,但管道元素都是 NULL 而不是 PLAYING 所以它不工作 gst_element_set_state(pipeline, GST_STATE_PLAYING);之前尝试gst_element_set_state(pipeline, GST_STATE_NULL); @moi 没有解决问题。有什么东西阻碍了我在管道中播放的过渡。 【参考方案1】:

根据您的管道的外观,进入 PLAYING 状态将始终异步发生(因此返回值 GST_STATE_CHANGE_ASYNC)。这是有道理的(例如:在某些情况下,设置连接、获取数据等需要一些时间),但与您的预期不同。

换句话说,如果你真的想检查你是否进入播放状态,你应该调用gst_element_get_state(),它实际上等待(并因此阻塞你的线程)状态改变发生。

GstStateChangeReturn ret;
GstState state;
GstState pending;

ret = gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE);
if (ret == GST_STATE_CHANGE_FAILURE) 
  MBPLog::Log(LM_CameraLibrary, LS_Error, "Pipeline would not play");
  return; // or whatever cleanup you want
 else 
  MBPLog::Log(LM_CameraLibrary, LS_Informational, "Pipeline is now in Playing state");
  // If you specified an actual timeout instead of GST_CLOCK_TIME_NONE,
  // you should check here if the return value is still
  // GST_STATE_CHANGE_SUCCESS of course.

【讨论】:

将 async 参数设置为 false 不能解决这个问题吗?顺便说一句,在完成我刚才描述的操作后,我不再获得 GST_STATE_CHANGE_ASYNC 的返回值。我现在得到一个返回值 1,这意味着成功,但是当我检查我的管道元素时,它们都是 NULL 而不是 PLAYING

以上是关于从暂停到播放时 Gstreamer 管道失败?的主要内容,如果未能解决你的问题,请参考以下文章

将管道设置为播放状态后,Gstreamer 回调未命中

gstreamer 仅播放视频

Gstreamer画中画 - 两个文件并行播放

Qt+GStreamer:如何在播放实时视频流时拍摄快照

使用 gst-rtsp-server 流式传输 H264 文件

C++ gstreamer函数使用总结