3

I wish to draw some UI on top of video stream that is rendered using Xoverlay. I am using gstreamer to play the video and render it on xvimagesink using xoverlay. My widget inherits from QGLWidget and I wish to draw 2D elements using QPainter I have done 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 reimplement paintEvent as follows

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 gets painted below the video. How do I overpaint it so that it shows above the video?

Bart
  • 19,692
  • 7
  • 68
  • 77
sinjar
  • 115
  • 2
  • 6

1 Answers1

1

There are two ways that I would go about this:

Try to have your painting happen as frequently as the video's painting.

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

Repainting Frequently

Qt is pretty smart about deciding when to repaint based on interactions with widgets, resizing, moving, update calls, etc. But Qt will also take those calls (which get turned into events in the GUI thread) and sometimes merge them to optimize for timing and processing. If you call repaint instead of update, then it should get called sooner. And you can try calling QApplication::processEvents() to have it use event changes sooner.

Higher Z Order

Whatever you are trying to paint on top of the video can get turned into a widget and moved on top of the video. You can make this overlay stay on top if you make sure that its flags make it superior to the video. The windowing system for the OS should make sure that one is above the other.

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

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

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

Also if you don't have a set geometry for your widget or its size isn't set, then it might not show up because it is only allowed to paint inside its geometry.

Let me know if you are still need more help.

Community
  • 1
  • 1
phyatt
  • 18,472
  • 5
  • 61
  • 80
  • The OS is Maemo 5. 1. repainting too often causes the overlay QWidget to flicker on the screen and also brings up the cpu usage. 2. I already tried setting the window flags to include Qt::WindowStaysOnTopHint and also WA_TranslucentBackground but still in vain.. I have even tried bypassing the X11 window manager but still no luck... Someone told me what i am trying to do is not possible as xoverlay uses vdpau calls.. But then i dont agree completely due to the fact that the default video player on Nokia N900 does paint controls on top of the video... Any ideas?? – sinjar Aug 02 '12 at 07:32
  • @sinjar I would contact an expert on the Maemo+Qt setup, maybe at http://qtcentre.org or post it as a bug on http://bugreports.qt-project.org . Maybe even trying to contact someone at Nokia for what they recommend for video playback and overlays. Sorry my solution has a limited solution space. – phyatt Aug 06 '12 at 23:18