我希望在使用Xoverlay呈现的视频流之上绘制一些UI。我正在使用gstreamer播放视频并使用xoverlay在xvimagesink上渲染它。 我的小部件继承自QGLWidget,我希望使用QPainter绘制2D元素 我做了以下事情:
VideoPlayer::VideoPlayer(QWidget *parent) :
QGLWidget(parent)
{
setAutoFillBackground(false);
QString fname = QFileDialog::getOpenFileName(0,tr("Open video"),tr("/"));
GstElement *pipeline,*source,*decoder,*q,*converter,*resampler,*audiosink,*videosink;
GstBus *bus;
pipeline = gst_pipeline_new("my-player");
source = gst_element_factory_make("filesrc","source");
decoder = gst_element_factory_make("decodebin2","decoder");
q = gst_element_factory_make("queue","q");
converter = gst_element_factory_make("audioconvert","converter");
resampler = gst_element_factory_make("audioresample","resampler");
audiosink = gst_element_factory_make("autoaudiosink","audio-sink");
videosink = gst_element_factory_make("xvimagesink","video-sink");
//Set the bin properties
g_object_set(G_OBJECT(source),"location",fname.toAscii().constData(),NULL);
g_object_set(G_OBJECT(decoder),"name","decoder");
gst_bin_add_many(GST_BIN(pipeline),source,decoder,q,converter,resampler,audiosink,videosink,NULL);
gst_element_link(source,decoder);
gst_element_link_many(q,converter,resampler,audiosink,NULL);
//gst_element_link(decoder,q);
g_signal_connect(decoder,"pad-added",G_CALLBACK(on_pad_added),videosink);
g_signal_connect(decoder,"pad-added",G_CALLBACK(on_pad_added),q);
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus,bus_call,NULL);
gst_object_unref(bus);
if (GST_IS_X_OVERLAY (videosink))
{
unsigned long win_id=winId();
QApplication::syncX();
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY(videosink),win_id);
}
gst_element_set_state(pipeline,GST_STATE_PLAYING);
}
然后我重新实现paintEvent,如下所示
void VideoPlayer::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.save();
painter.setPen(QColor(255,0,0,140));
painter.drawRect(QRectF(50,50,100,100));
painter.restore();
}
问题是矩形会在视频下方绘制。如何将其覆盖以显示在视频上方?
答案 0 :(得分:1)
我有两种方法可以解决这个问题:
尽量让你的绘画像视频的绘画一样频繁发生。
或创建一个单独的窗口小部件,其中包含一些窗口标记,强制它的z顺序高于您的视频(如您在问题中所建议的那样)。
Qt非常聪明,根据与小部件的交互,调整大小,移动,更新调用等来决定何时重新绘制。但是Qt也将接受这些调用(在GUI线程中转换为事件)并且有时将它们合并到优化时序和处理。如果你调用repaint而不是update,那么应该尽快调用它。您可以尝试调用QApplication :: processEvents()让它更快地使用事件更改。
无论你想在视频上绘制什么,都可以变成一个小部件并移到视频之上。如果您确保其标记使其优于视频,则可以使此叠加层保持在最顶层。操作系统的窗口系统应该确保一个在另一个之上。
这应该像获取VideoOverlay小部件一样简单(不是播放器,而是由播放器在堆上创建的单独的无父小部件),将其调整为视频之上(甚至可能连接到视频)您的播放器的resize事件,并将其窗口标志设置为Qt :: WindowStaysOnTop。您还需要将背景设置为透明,无框架等。您可能还需要使其对鼠标事件透明。
videoOverlay->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
videoOverlay->setAttribute(Qt::WA_TranslucentBackground);
我没有在你的代码上测试过这个,但是我已经在Windows中使用了这个设置用于很多小部件并取得了巨大的成功。这是我回答的一个问题,指的是png splash screen with transparency。
此外,如果您没有为窗口小部件设置几何图形或未设置其大小,则它可能不会显示,因为它只允许在其几何体内绘制。
如果您仍需要更多帮助,请告诉我。