【问题标题】:Draw on top of xoverlay using Qt使用 Qt 在 xoverlay 上绘制
【发布时间】:2012-04-03 10:12:41
【问题描述】:

我希望在使用 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();

}

问题是矩形被绘制在视频下方。如何对其进行重绘以使其显示在视频上方?

【问题讨论】:

    标签: qt opengl


    【解决方案1】:

    我有两种方法可以解决这个问题:

    尽量让您的绘画像视频中的绘画一样频繁出现。

    或者使用一些窗口标志创建一个单独的小部件,强制它在 z 顺序上高于您的视频(就像您在问题中建议的那样)。

    经常重绘

    Qt 非常聪明地根据与小部件的交互、调整大小、移动、更新调用等来决定何时重绘。但 Qt 也会接受这些调用(在 GUI 线程中变成事件),有时会将它们合并到优化时间和处理。如果你调用重绘而不是更新,那么它应该被更快地调用。您可以尝试调用 QApplication::processEvents() 让它更快地使用事件更改。

    高 Z 阶

    无论您试图在视频上绘制什么,都可以变成一个小部件并移动到视频上。如果您确保其标志使其优于视频,则可以使此叠加层保持在顶部。操作系统的窗口系统应该确保一个在另一个之上。

    这应该像获取 VideoOverlay 小部件(不是播放器,而是由播放器在堆上创建的单独的无父小部件)一样简单,将其大小调整为位于视频之上(甚至可能将其连接到播放器的调整大小事件,并将其窗口标志设置为 Qt::WindowStaysOnTop。您还需要设置背景透明和无框等。您可能还需要使其对鼠标事件透明。

    videoOverlay->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    videoOverlay->setAttribute(Qt::WA_TranslucentBackground);
    

    我尚未在您的代码上对此进行过测试,但我已将此设置用于 Windows 中的许多小部件,并取得了巨大成功。这是我不久前回答的一个问题,它指的是png splash screen with transparency

    此外,如果您没有为您的小部件设置几何图形或未设置其大小,则它可能不会显示,因为它只允许在其几何图形内绘制。

    如果您还需要更多帮助,请告诉我。

    【讨论】:

    • 操作系统是Maemo 5。 1. 重绘太频繁会导致overlay QWidget在屏幕上闪烁,同时也增加了cpu使用率。 2.我已经尝试将窗口标志设置为包括 Qt::WindowStaysOnTopHint 和 WA_TranslucentBackground 但仍然无效。我什至尝试绕过 X11 窗口管理器但仍然没有运气...有人告诉我我想做的是不可能,因为 xoverlay 使用 vdpau 调用。但是我不完全同意,因为诺基亚 N900 上的默认视频播放器确实在视频顶部绘制控件...有什么想法吗??
    • @sinjar 我会联系有关 Maemo+Qt 设置的专家,可能在 qtcentre.org 或将其作为错误发布在 bugreports.qt-project.org 上。甚至可能尝试联系诺基亚的某个人,了解他们对视频播放和叠加的建议。抱歉,我的解决方案空间有限。
    猜你喜欢
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多