【问题标题】:GStreamer c++ - seeking before starting any playbackGStreamer c++ - 在开始任何播放之前寻找
【发布时间】:2023-03-10 03:10:01
【问题描述】:

我使用 GStreamer 库向我的 C++ 应用程序添加了一个 start-offset 选项。它基本上告诉应用程序从中间视频开始,而不是从头开始播放。

管道是这样创建的:filesrc location="file_path" ! qtdemux ! h264parse ! mppvideodec ! waylandsink。这就是我在硬件上获得最佳结果的原因,而且我在 Weston (wayland) 下运行

我在管道上使用简单的gst_element_seek 进行搜索。首先,我尝试等到总线中的管道将状态更改为PLAYING 或PAUSED,然后再寻找一次。这行得通,但是在一些较大的视频上,它产生了一种效果,即在启动应用程序后,第一个视频帧会显示一秒钟,然后视频实际上会跳转到所需的位置。我不希望这样,我想直接跳到我想要的位置,而不显示任何其他内容。

因此,我什至在将管道设置为PLAYING 状态之前更改了我的搜索方法,如下所示:

// seek if needed
  if(startTime > 0) {
      // First set pipeline to PAUSED and wait for async state change
      gst_element_set_state(m_pipeline, GST_STATE_PAUSED);
      gst_element_get_state(m_pipeline, nullptr, nullptr, GST_CLOCK_TIME_NONE);
      if (!gst_element_seek (m_pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_NONE, -1)) {
        g_print ("Seek failed!\n");
      }
      gst_element_get_state(m_pipeline, nullptr, nullptr, GST_CLOCK_TIME_NONE); // wait for seek to finish and then set to PLAYING
  }
  m_ret = gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
  if (m_ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr("Unable to set the pipeline to the playing state.\n");
    gst_object_unref(m_pipeline);
    exit(0);
  }

虽然这也有效,但不幸的是,它产生了与以前完全相同的效果......即使在管道启动之前搜索发生,第一帧仍在显示。

如何确保在真正完成搜索之前不显示任何内容?

更新 我无法获得任何方法来寻求我想要的工作,但是我通过在构建管道之前在 GstVideoSink 上设置show-preroll-frame 来实现效果,如下所示:

m_sink = gst_element_factory_make("waylandsink", "sink");
g_object_set(m_sink, "show-preroll-frame", FALSE, NULL); // prevent preroll frame when seeking

而且它有效!如果没有更好的方法,我会暂时使用它。搜索仍然在PAUSED 状态下完成,但视频直接从搜索点显示。

【问题讨论】:

  • 看来用上面的方法搜索(播放前)使得第一帧看起来比状态改变后搜索更长...

标签: c++ gstreamer


【解决方案1】:

正如gst_element_seek_simple 方法的文档所说:

某些元素允许在 READY 状态下进行搜索...

如果管道在查找之前完全预滚动,则这是正确的。 然后你就可以得到你期望的结果,只显示你期望的帧。

 gst_element_set_state(m_pipeline, GST_STATE_READY);
 //make sure all the pipeline is prerolled (dynamic pads linked and other stuff)
 if (!gst_element_seek (m_pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_NONE, -1)) {
    g_print ("Seek failed!\n");
  }
  gst_element_get_state(m_pipeline, nullptr, nullptr, GST_CLOCK_TIME_NONE);

【讨论】:

  • 这很遗憾导致“Seek failed”消息,如何确保管道已预卷?我尝试在第一个 ...set_state 下添加额外的 gst_element_get_state,但没有帮助
  • 或者这是否意味着我的元素不支持在READY 状态下查找?我目前尝试在收到状态更改为 GST_STATE_READY、GST_STATE_PAUSED 或 GST_STATE_PLAYING 时进行搜索,并且我在 PAUSED 状态下首次成功搜索
  • 我在 gstvideosink 的一些旧文档中找到了一个 show-preroll-frame,有什么方法可以在 C++ 中的 Waylandsink 中使用它吗?我认为它可以满足我的需求。
  • 是的!它完成了工作。我在构建管道之前添加了这一行g_object_set(m_sink, "show-preroll-frame", FALSE, NULL); // prevent preroll frame when seeking ,它可以工作,在搜索完成之前什么都不会显示。如果有人有更好的方法,我会等待,如果没有,我会添加它作为答案
  • 在我的例子中,我使用的是 decodebin 元素,所以我需要在搜索之前链接所有动态创建的焊盘。我用 pad_added_handler 信号控制它。全部链接后,就可以在就绪状态下执行搜索
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多