Рисуем поверх xoverlay используя Qt
Я хочу нарисовать некоторый пользовательский интерфейс поверх видеопотока, который отображается с использованием 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 ответ
Есть два способа сделать это:
Постарайтесь, чтобы ваша картина происходила так же часто, как картина на видео.
Или создайте отдельный виджет с некоторыми флажками окна, который заставляет его быть выше в порядке z, чем ваше видео (как вы предложили в своем вопросе).
Перекрасить часто
Qt довольно умно решает, когда перерисовывать, основываясь на взаимодействиях с виджетами, изменении размера, перемещении, обновлении вызовов и т. Д. Но Qt также будет принимать эти вызовы (которые превращаются в события в потоке GUI) и иногда объединять их для оптимизации по времени и обработка. Если вы вызываете repaint вместо update, то он должен вызываться раньше. И вы можете попробовать вызвать QApplication::processEvents(), чтобы он использовал изменения событий раньше.
Высший Z Порядок
Все, что вы пытаетесь нарисовать поверх видео, может быть превращено в виджет и перемещено поверх видео. Вы можете сделать это наложение, если вы уверены, что его флаги делают его лучше, чем видео. Система управления окнами для ОС должна быть уверена, что одна находится над другой.
Это должно быть так же просто, как взять ваш виджет VideoOverlay (не проигрыватель, а отдельный виджет без родителей, который создается в куче вашим плеером), изменить его размер, чтобы он был поверх видео (и, возможно, даже подключить его к событию resize). для вашего плеера и установите для его флагов окна значение Qt::WindowStaysOnTop. Вам также понадобится установить прозрачный фон и безрамку и т. д. Также может потребоваться сделать его прозрачным для событий мыши.
videoOverlay->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
videoOverlay->setAttribute(Qt::WA_TranslucentBackground);
Я не проверял это в вашем коде, но с большим успехом использовал эту настройку для ряда виджетов в Windows. Вот вопрос, на который я недавно ответил, который относится к заставке png с прозрачностью.
Также, если у вас нет заданной геометрии для вашего виджета или его размер не задан, то он может не отображаться, потому что ему разрешено рисовать только внутри его геометрии.
Дайте мне знать, если вам все еще нужна помощь.