Соединить Gstreamer с Qt для воспроизведения видео с gstreamer в виджете Qt - PullRequest
4 голосов
/ 12 февраля 2010

Я пытался использовать фонон для воспроизведения видео, но не смог. Офф-поздно стало известно на форумах Qt, что даже последняя версия Qt не поддерживает фононы. Именно тогда я начал использовать Gstreamer. Есть предложения, как связать окно Gstreamer с виджетом Qt? Моя цель - воспроизвести видео с помощью Gstreamer в виджете Qt. Так как мне связать окно Gstreamer и виджет Qt?

Мне удалось получить Id виджета через winid(). Далее с помощью Григория Пакоша я добавил следующие 2 строки кода в свое приложение -

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 () в моем контексте?

Могу ли я получить какой-нибудь намек на то, как я могу интегрировать gstreamer в Qt? Пожалуйста, помогите мне решить эту проблему.

Ответы [ 4 ]

2 голосов
/ 26 марта 2010

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

имеет минимальный пример Qt.

В вашем коде вам, вероятно, следует установить идентификатор окна перед тем, как изменить состояние на готовое (хотя я не уверен на 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);

.. проверять сообщения типа error / statechanges / tags / eos на конвейере / шине воспроизведения

1 голос
/ 03 ноября 2010

Пример кода, приведенный выше, свяжет видеоокно GStreamer с QtWidget, если элементы связаны правильно.

  • filesrc должен быть связан с демультиплексором
  • декодер должен быть связан с fileink
  • Наконец, демультиплексор должен быть связан с декодером во время выполнения
// 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);
  }
}
1 голос
/ 30 марта 2010

Я только что сделал то же самое, используя python. Мне нужно было подключиться к «sync-message :: element» на шине и прослушать сообщение «prepare-xwindow-id» (игнорировать имя, так как оно работает на всех платформах, не только X11), отправленное после видео сток настроен. Он отправляет вам приемник внутри этого сообщения, и именно там вы передаете ему идентификатор окна.

0 голосов
/ 14 февраля 2010

Проект, оборачивающий gstreamer в пригодные для использования классы C ++ / Qt, включая пример кода: http://code.google.com/p/qbtgstreamer/

Я не знаю о прямом подходе, поскольку я не знаком с самим gstreamer.

...