摘要

  通常我们的播放引擎需要和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

 View Code

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