GStreamer基础教程11 - 与QT集成
摘要
通常我们的播放引擎需要和GUI进行集成,在使用GStreamer时,GStreamre会负责媒体的播放及控制,GUI会负责处理用户的交互操作以及创建显示的窗口。本例中我们将结合QT介绍如何指定GStreamer将视频输出到指定窗口,以及如何利用GStreamer上报的信息去更新GUI。
与GUI集成
我们知道与GUI集成有两个方面需要注意:
- 显示窗口的管理。
由于显示窗口通常由GUI框架创建,所以我们需要将具体的窗口信息告诉GStreamer。由于各个平台使用不同的方式传递窗口句柄,GStreamer提供了一个抽象接口(GstVideoOverlay),用于屏蔽平台的差异,我们可以直接将GUI创建的窗口ID传递给GStreamer。
- GUI界面的更新
大多数GUI框架都需要在主线程中去做UI的刷新操作,但GStreamer内部可能会创建多个线程,这就需要通过GstBus及GUI自带的通信机制将所有GStreamer产生的消息传递到GUI主线程,再由GUI主线程对界面进行刷新。
下面我们将以QT为例来了解如何处理GStreamer与GUI框架的集成。
示例代码
qtoverlay.h

qtoverlay.cpp
#include <gst/video/videooverlay.h> #include <QApplication> #include "qtoverlay.h" PlayerWindow::PlayerWindow(GstElement *p) :pipeline(p) ,state(GST_STATE_NULL) ,totalDuration(GST_CLOCK_TIME_NONE) { playBt = new QPushButton("Play"); pauseBt = new QPushButton("Pause"); stopBt = new QPushButton("Stop"); videoWindow = new QWidget(); slider = new QSlider(Qt::Horizontal); timer = new QTimer(); connect(playBt, SIGNAL(clicked()), this, SLOT(onPlayClicked())); connect(pauseBt, SIGNAL(clicked()), this, SLOT(onPauseClicked())); connect(stopBt, SIGNAL(clicked()), this, SLOT(onStopClicked())); connect(slider, SIGNAL(sliderReleased()), this, SLOT(onSeek())); buttonLayout = new QHBoxLayout; buttonLayout->addWidget(playBt); buttonLayout->addWidget(pauseBt); buttonLayout->addWidget(stopBt); buttonLayout->addWidget(slider); playerLayout = new QVBoxLayout; playerLayout->addWidget(videoWindow); playerLayout->addLayout(buttonLayout); this->setLayout(playerLayout); connect(timer, SIGNAL(timeout()), this, SLOT(refreshSlider())); connect(this, SIGNAL(sigAlbum(QString)), this, SLOT(onAlbumAvaiable(QString))); connect(this, SIGNAL(sigState(GstState)), this, SLOT(onState(GstState))); connect(this, SIGNAL(sigEos()), this, SLOT(onEos())); } WId PlayerWindow::getVideoWId() const { return videoWindow->winId(); } void PlayerWindow::onPlayClicked() { GstState st = GST_STATE_NULL; gst_element_get_state (pipeline, &st, NULL, GST_CLOCK_TIME_NONE); if (st < GST_STATE_PAUSED) { // Pipeline stopped, we need set overlay again GstElement *vsink = gst_element_factory_make ("ximagesink", "vsink"); g_object_set(GST_OBJECT(pipeline), "video-sink", vsink, NULL); WId xwinid = getVideoWId(); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (vsink), xwinid); } gst_element_set_state (pipeline, GST_STATE_PLAYING); } void PlayerWindow::onPauseClicked() { gst_element_set_state (pipeline, GST_STAT