Рисуем поверх xoverlay используя Qt - PullRequest
3 голосов
/ 18 марта 2012

Я хочу нарисовать некоторый пользовательский интерфейс поверх видеопотока, который отображается с использованием Xoverlay.Я использую gstreamer для воспроизведения видео и рендеринга его на xvimagesink с помощью xoverlay.Мой виджет наследуется от QGLWidget, и я хочу рисовать 2D-элементы с помощью QPainter. Я сделал следующее:

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

}

Проблема в том, что прямоугольникраскрашивается под видео.Как мне перекрасить его так, чтобы оно показывалось над видео?

1 Ответ

1 голос
/ 26 июня 2012

Есть два способа сделать это:

Постарайтесь, чтобы рисование происходило так же часто, как рисование видео.

Или создайте отдельный виджет с некоторыми флажками окна, который заставляетон должен быть выше по порядку z, чем ваше видео (как вы предложили в своем вопросе).

Перекрашивание часто

Qt довольно умно решает, когда перерисовывать, основываясь на взаимодействиях с виджетами, изменяя размеры,перемещение, обновление вызовов и т. д. Но Qt также будет принимать эти вызовы (которые превращаются в события в потоке GUI) и иногда объединять их для оптимизации времени и обработки.Если вы вызываете repaint вместо update, то он должен быть вызван раньше.И вы можете попробовать вызвать QApplication :: processEvents (), чтобы он использовал изменения событий раньше.

Более высокий порядок Z

Все, что вы пытаетесь нарисовать поверх видео, может превратиться ввиджет и переместился поверх видео.Вы можете сделать это наложение, если вы уверены, что его флаги делают его лучше, чем видео.Система управления окнами для ОС должна быть уверена, что одно находится над другим.

Это должно быть так же просто, как взять ваш виджет VideoOverlay (не проигрыватель, а отдельный виджет без родителей, который создается в куче вашимplayer), изменив его размер, чтобы он был поверх видео (и, возможно, даже подключив его к событию resize для вашего плеера, и установите для его флагов окна значение Qt :: WindowStaysOnTop. Вам также нужно будет установить фон прозрачным и безрамными т. д. Вам также может понадобиться сделать его прозрачным для событий мыши.

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

Я не проверял это в вашем коде, но с большим успехом использовал эту настройку для ряда виджетов в WindowsВот вопрос, на который я недавно ответил, который относится к заставке png с прозрачностью .

Также, если у вас нет заданной геометрии для вашего виджета или его размер нене устанавливается, тогда он может не отображаться, потому что ему разрешено рисовать только внутри его геометрии.

Дайте мне знать, если вы неВам понадобится дополнительная помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...