将 Gstreamer 与 Qt 连接以便在 Qt Widget 中播放 gstreamer 视频

发布于 2024-08-21 10:30:13 字数 1925 浏览 6 评论 0原文

我尝试使用 phonon 播放视频,但未能成功。 Off-late通过Qt论坛了解到,即使是最新版本的Qt也不支持phonon。就在那时我开始使用 Gstreamer。关于如何将 Gstreamer 窗口与 Qt 小部件连接有什么建议吗?我的目标是在 Qt 小部件上使用 Gstreamer 播放视频。那么如何链接 Gstreamer 窗口和 Qt 小部件呢?

我通过winid()成功获取了小部件的Id。 此外,在 Gregory Pakosz 的帮助下,我在我的应用程序中添加了以下两行代码 -

QApplication::syncX();
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), widget->winId());

但是我无法将 Qt 小部件与 gstreamer 视频窗口链接。

这就是我的示例代码看起来像:-

int main(int argc, char *argv[])
{
printf("winid=%d\n", w.winId());
    gst_init (NULL,NULL);
    /* create a new bin to hold the elements */
    bin = gst_pipeline_new ("pipeline");

      /* create a disk reader */
  filesrc = gst_element_factory_make ("filesrc", "disk_source");
  g_assert (filesrc);



  g_object_set (G_OBJECT (filesrc), "location", "PATH_TO_THE_EXECUTABLE", NULL);

  demux = gst_element_factory_make ("mpegtsdemux", "demuxer");
  if (!demux) {
    g_print ("could not find plugin \"mpegtsmux\"");
    return -1;
  }

  vdecoder = gst_element_factory_make ("mpeg2dec", "decode");
  if (!vdecoder) {
    g_print ("could not find plugin \"mpeg2dec\"");
    return -1;
  }

  videosink = gst_element_factory_make ("xvimagesink", "play_video");
  g_assert (videosink);


  /* add objects to the main pipeline */

  gst_bin_add_many (GST_BIN (bin), filesrc, demux, vdecoder, videosink, NULL);


  /* link the elements */
  gst_element_link_many (filesrc, demux, vdecoder, videosink, NULL);

    gst_element_set_state(videosink, GST_STATE_READY);

    QApplication::syncX();
    gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());



  /* start playing */
  gst_element_set_state (bin, GST_STATE_PLAYING);

}

您能否更详细地解释一下 gst_x_overlay_set_xwindow_id() 在我的上下文中的用法?

我可以获得有关如何在 Qt 下集成 gstreamer 的任何提示吗? 请帮我解决这个问题。

I tried using phonon to play the video but could not succeed. Off-late came to know through the Qt forums that even the latest version of Qt does not support phonon. That's when I started using Gstreamer. Any suggestions as to how to connect the Gstreamer window with the Qt widget? My aim is to play a video using Gstreamer on the Qt widget. So how do I link the Gstreamer window and the Qt widget?

I am successful in getting the Id of the widget through winid().
Further with the help of Gregory Pakosz, I have added the below 2 lines of code in my application -

QApplication::syncX();
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), widget->winId());

However am not able to link the Qt widget with the gstreamer video window.

This is what my sample code would look like :-

int main(int argc, char *argv[])
{
printf("winid=%d\n", w.winId());
    gst_init (NULL,NULL);
    /* create a new bin to hold the elements */
    bin = gst_pipeline_new ("pipeline");

      /* create a disk reader */
  filesrc = gst_element_factory_make ("filesrc", "disk_source");
  g_assert (filesrc);



  g_object_set (G_OBJECT (filesrc), "location", "PATH_TO_THE_EXECUTABLE", NULL);

  demux = gst_element_factory_make ("mpegtsdemux", "demuxer");
  if (!demux) {
    g_print ("could not find plugin \"mpegtsmux\"");
    return -1;
  }

  vdecoder = gst_element_factory_make ("mpeg2dec", "decode");
  if (!vdecoder) {
    g_print ("could not find plugin \"mpeg2dec\"");
    return -1;
  }

  videosink = gst_element_factory_make ("xvimagesink", "play_video");
  g_assert (videosink);


  /* add objects to the main pipeline */

  gst_bin_add_many (GST_BIN (bin), filesrc, demux, vdecoder, videosink, NULL);


  /* link the elements */
  gst_element_link_many (filesrc, demux, vdecoder, videosink, NULL);

    gst_element_set_state(videosink, GST_STATE_READY);

    QApplication::syncX();
    gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());



  /* start playing */
  gst_element_set_state (bin, GST_STATE_PLAYING);

}

Could you explain more in detail about the usage of gst_x_overlay_set_xwindow_id() wrt my context?

Could I get any hint as to how I can integrate gstreamer under Qt?
Please help me solve this problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

血之狂魔 2024-08-28 10:30:13

我刚刚使用 python 做了同样的事情。我要做的就是连接到总线上的“sync-message::element”,并侦听在视频接收器已设置。它向您发送该消息内的接收器,这就是您向其传递窗口 ID 的地方。

I just did this same thing using python. What I had to do was connect to 'sync-message::element' on the bus and listen for a message called 'prepare-xwindow-id' (disregard the name as it works on all platforms, not just X11) sent after the video sink is setup. It sends you the sink inside that message, and that is where you pass it the window id.

春庭雪 2024-08-28 10:30:13

如果元素链接正确,上面给出的示例代码会将 GStreamer 视频窗口链接到 QtWidget。

  • filesrc 应链接到解复用器
  • 解码器 应链接到文件接收器
  • 最后,解复用器应在运行时链接到解码器
// link filesrc to demuxer
gst_element_link(filesrc,demux)

// link vdecoder to filesink
gst_element_link_many(vdecoder,filesink,NULL)

/*
  The demuxer will be linked to the decoder dynamically.
  The source pad(s) will be created at run time,
  by the demuxer when it detects the amount and nature of streams.
  Connect a callback function which will be executed
  when the "pad-added" is emitted.
*/

g_signal_connect(demux,"pad-added",G_CALLBACK(on_pad_added),vdecoder);

// callback definition
static void on_pad_added(GstElement* element,GstPad* pad,gpointer* data)
{
  GstPad* sinkpad;
  GstElement * decoder = (GstElement*)data;
  GstCaps* caps;
  GstStructure* str;
  gchar* tex;

  caps = gst_pad_get_caps(pad);
  str = gst_caps_get_structure(caps,0);
  tex = (gchar*)gst_structure_get_name(str);

  if(g_strrstr(tex,"video"))
  {
    sinkpad = gst_element_get_static_pad(decoder,"sink");
    gst_pad_link(pad,sinkpad);
    gst_object_unref(sinkpad);
  }
}

The sample code given above will link GStreamer video window to QtWidget provided the elements are linked correctly.

  • filesrc should be linked to the demuxer
  • decoder should be linked to the filesink
  • Finally, the demuxer should be linked to the decoder at runtime
// link filesrc to demuxer
gst_element_link(filesrc,demux)

// link vdecoder to filesink
gst_element_link_many(vdecoder,filesink,NULL)

/*
  The demuxer will be linked to the decoder dynamically.
  The source pad(s) will be created at run time,
  by the demuxer when it detects the amount and nature of streams.
  Connect a callback function which will be executed
  when the "pad-added" is emitted.
*/

g_signal_connect(demux,"pad-added",G_CALLBACK(on_pad_added),vdecoder);

// callback definition
static void on_pad_added(GstElement* element,GstPad* pad,gpointer* data)
{
  GstPad* sinkpad;
  GstElement * decoder = (GstElement*)data;
  GstCaps* caps;
  GstStructure* str;
  gchar* tex;

  caps = gst_pad_get_caps(pad);
  str = gst_caps_get_structure(caps,0);
  tex = (gchar*)gst_structure_get_name(str);

  if(g_strrstr(tex,"video"))
  {
    sinkpad = gst_element_get_static_pad(decoder,"sink");
    gst_pad_link(pad,sinkpad);
    gst_object_unref(sinkpad);
  }
}
_蜘蛛 2024-08-28 10:30:13

http://cgit.freedesktop.org/gstreamer/ gst-plugins-base/tree/tests/examples/overlay

有一个最小的 Qt 示例。

在您的代码中,您应该在将状态更改为就绪之前设置窗口 ID(尽管我不能 100% 确定这是问题所在)。

对于播放,您最好使用 playbin2 元素,如下所示(完全未经测试):

GstElement *playbin, *videosink;
gchar *uri;

 playbin = gst_element_factory_make ("playbin2", "myplaybin");
 videosink = gst_element_factory_make ("xvimagesink", NULL);

 g_object_set (playbin, "video-sink", videosink, NULL);

 uri = g_filename_to_uri ("/path/to/file", NULL, NULL);
 g_object_set (playbin, "uri", uri, NULL);
 g_free (uri);

 /* NOTE: at this point your main window needs to be realized,
  * ie visible on the screen, and you might need to make sure
  * that your widget w indeed has a 'native window' (just some
  * things to check for if it doesn't work; there should be Qt
  * API for this kind of thing if needed) */
 QApplication::syncX();
 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());

 gst_element_set_state (playbin, GST_STATE_PLAYING);

.. 检查管道/playbin 总线上的错误/状态更改/标签/eos 等消息

http://cgit.freedesktop.org/gstreamer/gst-plugins-base/tree/tests/examples/overlay

has a minimal Qt example.

In your code, you should probably set the window ID before you do the state change to ready (I'm not 100% sure this is the problem though).

For playback, you should idally use the playbin2 element, something like this (completely untested):

GstElement *playbin, *videosink;
gchar *uri;

 playbin = gst_element_factory_make ("playbin2", "myplaybin");
 videosink = gst_element_factory_make ("xvimagesink", NULL);

 g_object_set (playbin, "video-sink", videosink, NULL);

 uri = g_filename_to_uri ("/path/to/file", NULL, NULL);
 g_object_set (playbin, "uri", uri, NULL);
 g_free (uri);

 /* NOTE: at this point your main window needs to be realized,
  * ie visible on the screen, and you might need to make sure
  * that your widget w indeed has a 'native window' (just some
  * things to check for if it doesn't work; there should be Qt
  * API for this kind of thing if needed) */
 QApplication::syncX();
 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());

 gst_element_set_state (playbin, GST_STATE_PLAYING);

.. check for messages like error/statechanges/tags/eos on pipeline/playbin bus

趁年轻赶紧闹 2024-08-28 10:30:13

将 gstreamer 包装到可用的 C++/Qt 类中的项目,包括示例代码:
http://code.google.com/p/qbtgstreamer/

我不知道关于直接方法,因为我对 gstreamer 本身不熟悉。

A project wrapping gstreamer into usable C++/Qt classes including example code:
http://code.google.com/p/qbtgstreamer/

I don't know about a direct approach, as I am not familiar with gstreamer itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文