Draw over the xoverlay with Qt

I want to draw some UI on top of a video stream that is rendered using Xoverlay. I am using gstreamer to play a video and render it to xvimagesink using xoverlay. My widget inherits from QGLWidget and I want to draw 2D items using QPainter I did the following:

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);
}

      

Then I re-implement paintEvent like this

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();

}

      

The problem is that the rectangle is colored under the video. How do I recolor it so that it appears above the video?

+3


source to share


1 answer


There are two ways I would do it:

Try to have your picture happen as often as the video.

Or create a separate widget with some Window flags that cause it to be higher in z-order than your video (like you suggested in your question).

Re-painting

Qt is pretty good at figuring out when to redraw based on interaction with widgets, resizing, moving, updating calls, etc. But Qt will also accept these calls (which turn into events on the GUI thread) and sometimes combine them to optimize timing and handling. If you are calling redraw instead of updating, then it needs to be called earlier. And you can try calling QApplication :: processEvents () to use event changes earlier.

Higher Z-order



Anything you try to paint over the video can be turned into a widget and moved over the video. You can do this overlay on top if you make sure its flags are superior to the video. The windowing system for the OS needs to make sure it sits on top of the other.

It should be as simple as taking a VideoOverlay widget (not a player, but a separate parentless widget that is created in the heap by your player), resizing it on top of the video (and maybe even connecting it to a resize event for your player and set the window flags as Qt :: WindowStaysOnTop You will also need to set the background transparent and frameless, etc. You may also need to make it transparent for mouse events.

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

      

I haven't tested this on your code, but I've used this setup for a number of widgets on Windows with great success. Here is a question I answered a while ago that relates to a png screen with transparency .

Also, if you do not have a given geometry for your widget, or it is not sized, it may not display because it is only allowed to draw within its geometry.

Let me know if you still need more help.

+1


source







All Articles