【问题标题】:GStreamer freezes at first frameGStreamer 在第一帧冻结
【发布时间】:2017-12-05 12:09:26
【问题描述】:

我希望拆分 GStreamer 管道,以便显示和录制视频。我使用以下管道与 gst-launch 一起工作:

gst-launch-1.0 -v videotestsrc !视频/x-raw,宽度=640,高度=480 tee 名称=“t”!队列 !下载! glimagesink t。 !队列 !杰佩根! ! 文件接收器位置=输出.avi

我尝试在我的 C++ 应用程序中实现这一点,但遇到了一个对我来说没有意义的问题。下面是整个管道设置,但只有最后几行是相关的/有趣的。

gst_init (NULL, NULL);

GstElement *pipeline = gst_pipeline_new(NULL);
GstElement *sink = NULL;

GstElement *src = gst_element_factory_make("videotestsrc", NULL);
g_assert(src);

GstElement *filter = gst_element_factory_make("capsfilter", "filter");
g_assert(filter);

g_object_set(G_OBJECT (filter), "caps", gst_caps_new_simple("video/x-raw", 
    "width", G_TYPE_INT, 640,
    "height", G_TYPE_INT, 480,
    NULL), 
NULL);

GstElement *convert = gst_element_factory_make("videoconvert", NULL);
g_assert(convert);

// Tee
GstElement *tee = gst_element_factory_make("tee", "videotee");
g_assert(GstElement *tee);

// Display queue
GstElement *displayQueue = gst_element_factory_make("queue", "displayQueue");
g_assert(displayQueue);


GstElement *upload = gst_element_factory_make("glupload", NULL);
g_assert(upload);


sink = gst_element_factory_make("qmlglsink", NULL);
g_assert(sink);

// Record queue
GstElement *recordQueue = gst_element_factory_make("queue", "recordQueue");
g_assert(recordQueue);

GstElement *encode = gst_element_factory_make("jpegenc", NULL);
g_assert(encode);

GstElement *mux = gst_element_factory_make("avimux", NULL);
g_assert(mux);

GstElement *filesink = gst_element_factory_make("filesink", NULL);
g_assert(filesink);

g_object_set(G_OBJECT(filesink), "location", "output.avi", NULL);

// The above is not interesting, just included it for completeness

// Add elements to bin
gst_bin_add_many(GST_BIN (pipeline), src, filter, convert, tee, displayQueue, upload, sink, recordQueue, encode, mux, filesink, NULL);

// Link elements
gst_element_link_many(src, filter, convert, tee, NULL);
gst_element_link_many(tee, displayQueue, upload, sink, NULL);
//gst_element_link_many(tee, recordQueue, encode, mux, filesink, NULL);

如果我不将 filesink 添加到 bin,则测试视频会按预期显示。如果我将 filesink 添加到 bin 中,则视频会显示第一帧然后冻结。我不明白为什么会这样,因为我还没有将 filesink 链接到管道(该行已被注释掉)。

有人知道这是为什么吗?

(如果我取消注释记录队列链接到管道的行,则不会显示任何内容。但这可能是以后的问题。)

更新

我尝试使用 gst_parse_launch() 运行管道,它显示了相同的行为。

GError *error = NULL;
GstPipeline *pipeline;
pipeline = GST_PIPELINE(gst_parse_launch("videotestsrc  ! video/x-raw,width=640,height=480 tee name='t' ! queue ! glupload ! glimagesink t. ! queue ! jpegenc ! avimux ! filesink location=output.avi", &error));
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);

上面的代码在第一帧冻结,并且创建了 output.avi 文件,但大小为 0 字节。如果我删除文件接收器队列,则视频显示正常。

作品:

videotestsrc !视频/x-raw,width=640,height=480 tee name="t" !队列 ! 下载! glimagesink

不起作用:

videotestsrc !视频/x-raw,width=640,height=480 tee name="t" !队列 ! 下载! glimagesink t。 !队列 !杰佩根! !文件接收器 位置=输出.avi

所以我想我的文件接收器插件有问题。我尝试使用文件的绝对路径,但这没有帮助。 (当我从终端使用 gst-launch 时它仍然可以正常工作)

我也试过用环境变量GST_DEBUG="filesink:9"打印一些调试信息,但它没有打印任何错误,只有这个信息:

0:00:00.116304411 3331 0x7f92b4002f60 INFO 文件接收器 gstfilesink.c:301:gst_file_sink_set_location: 文件名: /some/path/output.avi

0:00:00.116345776 3331 0x7f92b4002f60 INFO 文件接收器 gstfilesink.c:302:gst_file_sink_set_location: uri: file:///some/path/output.avi

0:00:00.118291875 3331 0x7f92b4002f60 调试文件接收器 gstfilesink.c:523:gst_file_sink_do_seek:寻求抵消 0 使用 fseeko

0:00:00.118320893 3331 0x7f92b4002f60 调试文件接收器 gstfilesink.c:423:gst_file_sink_open_file: 打开 文件 /some/path/output.avi,可查找 1

有人知道是什么原因造成的吗?

【问题讨论】:

  • 为什么是 C 和 C++ 标签?这与编写代码的编程语言无关。
  • 代码是用 C/C++ 编写的。我正在使用 C 的 GStreamer 库并在我的 C++ 应用程序中使用它。可能有其他语言的 GStreamer 库,但只有 C/C++ 的 GStreamer 是相关的,因此我添加了标签。
  • 与 Qt 也没有太大关系。我怀疑可以从上面的例子中给出答案。除了所有这些代码对于组成 GStreamer 管道可能不正确之外,我不能添加太多。最好尝试查找有关如何使用 gst_parse_launch() gist.github.com/nzjrs/725122/… 的信息以及其他示例。至少你会将该任务委派给 GStreamer 本身。
  • @KMK,这仍然与 C 或 C++ 作为编程语言无关。您也没有用“英语”标记您的问题。
  • 随着你的最新更新,你有一个管道 "pipeline = GST_PIPELINE(gst_parse_launch("videotestsrc ! video/x-raw,width=640,height=480 tee name='t' ! queue ! glupload ! glimagesink t. ! queue ! jpegenc !avimux !filesink location=output.avi", &error));"它需要是 pipeline = GST_PIPELINE(gst_parse_launch("videotestsrc !video/x-raw,width=640,height=480 !tee name='t' !queue !glupload !glimagesink t 。!queue !jpegenc !avimux !filesink 位置=output.avi", &error));你错过了一个“!”在 caps 过滤器之后和 tee 元素之前

标签: c gstreamer


【解决方案1】:

您可以先使用简单的选项,即使用 gst_parse_launch(),而不是创建元素并连接焊盘。

遇到冻结的问题,元素的链接不正确 它需要遵循:

 // Link elements
gst_element_link_many(src, filter, convert, tee, NULL);

/* Manually link the Tee, which has "Request" pads */
  GstPad *tee_display_pad = gst_element_get_request_pad (tee, "src_%u");
  GstPad *queue_display_pad = gst_element_get_static_pad (displayQueue, "sink");

  GstPad *tee_video_pad = gst_element_get_request_pad (tee, "src_%u");
  GstPad *queue_video_pad = gst_element_get_static_pad (recordQueue, "sink");

  if (gst_pad_link (tee_display_pad, queue_display_pad) != GST_PAD_LINK_OK ||
      gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK)
    return -1;

  gst_object_unref (tee_display_pad);
  gst_object_unref (queue_display_pad);
  gst_object_unref (tee_video_pad);
  gst_object_unref (queue_video_pad);

  gst_element_link_many(displayQueue, upload, sink, NULL);

gst_element_link_many(recordQueue, encode, mux, filesink, NULL);

【讨论】:

  • 我尝试了使用 gst_parse_launch() 和使用您的示例中的垫,但是当文件接收器添加到管道时,它仍然在第一帧冻结。所以我想我的文件接收器插件有问题......
  • 您确实在您的第一篇文章“gst-launch-1.0 -v videotestsrc!video/x-raw,width=640,height=480!tee name="t “!queue!glupload!glimagesink t.!queue!jpegenc!avimux!filesink location=output.avi”,理想情况下使用gst_parse_launch()它应该可以工作,你能发布你的完整代码吗?也许还有别的东西!
  • 我有多个包含大量代码的文件,所以我尝试只发布相关的内容。但是,我所有关于 GStreamer 的代码都在上面发布。我还添加了 gst_parse_launch() 的代码
猜你喜欢
  • 1970-01-01
  • 2022-12-22
  • 2015-04-28
  • 1970-01-01
  • 2012-10-14
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
相关资源
最近更新 更多