Rendering a QGraphicsScene with QGraphicsVideoItem to QImage

1.5k views Asked by At

This part is solved

I want to render a QGraphicsScene with QGraphicsVideoItem to QImage. Everything works when the QGraphicsScene is just with a QGraphicsTextItem. However, if I replace QGraphicsTextItem with a QGraphicsVideoItem, it fails to get a correct image output. How to fix this? Thanks... following codes are to test this problem.

#include <QApplication>
#include <QGraphicsScene>
#include <QMediaPlayer>
#include <QGraphicsVideoItem>
#include <QImage>
#include <QGraphicsView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QGraphicsScene scene;
    /* part 1. videoItem */
    QMediaPlayer* videoPlayer = new QMediaPlayer;
    QGraphicsVideoItem* screen = new QGraphicsVideoItem;
    videoPlayer->setVideoOutput(screen);
    scene.addItem(screen);
    videoPlayer->setMedia(QUrl::fromLocalFile("./data/Taylor Swift - Blank Space.mp4"));
    videoPlayer->play();
    videoPlayer->setVolume(100);

    /* part 2. textItem  */
    /*QGraphicsScene scene;
    QGraphicsTextItem* text = new QGraphicsTextItem("aaaaaaa");
    scene.addItem(text);*/

    QGraphicsView view(&scene);
    view.resize(1920, 1080);
    view.show();
    videoPlayer->pause();


    QImage image(1920, 1080, QImage::Format_ARGB32);
    image.fill(Qt::blue);
    QString pngName = "scene.png";
    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);

    scene.render(&painter);
    image.save(pngName);

    return a.exec();
}

add the following in your .pro file may help : )

QT       += core gui
QT       += core
#QT       += 3d
QT       += gui
QT       += multimedia
QT       += widgets
QT       += multimediawidgets

new Question

In my project I want to render a video in a QGLView Window(Qt3D). However, QGraphicsView and QGLView seems can not be rendered at the same time. If I don't use QGLView's show() method, I can get the video frames. If I use QGLView's show() method, I cannot get correct frames...

So how could I realize the idea above?

1

There are 1 answers

2
hyde On BEST ANSWER

The video is usually decoded and rendered using HW acceleration, so asking for the widget to be painted like that might not work at all, or at least it depends on the actual video player backend.

You could use QScreen::grabWindow (assuming Qt 5, it was QPixmap::grabWindow in Qt 4), after the screen is actually rendered. To actually have any video, you need to grab the screenshow when video is actually showing, so you have to do it once the event loop is running and window is actually shown, for example by overrding showEvent or just using QTimer.

If you want a screenshot of both the video and the GUI without actually showing the window, I'm not sure how to go about that.