Peter Winzell
Peter Winzell

Reputation: 1

How to QVideoFrame to QImage

The task is to copy a frame from a QVideoFrame, and possibly do something to that Image and displaying the manipulated Image in QML.

...

m_lastFrame = QImage(videoFrame.width(), videoFrame.height(), QImage::Format_ARGB32);
memcpy(m_lastFrame.bits(), videoFrame.bits(),videoFrame.mappedBytes());

...

The above code causes a crash, since m_lastFrame is short of 32 bytes(3686400 vs 3686432) videoFrame.mappedBytes() reports 3686432 bytes. What am I doing wrong here? Or how should I calculate the size of m_lastFrame().

The code is running on Mac OSx 10.9.5 Qt 5.1.1.

Some additional code:

... if( videoFrame.map(QAbstractVideoBuffer::ReadOnly) ){

    m_lastFrame = QImage(videoFrame.width(),videoFrame.height(),QImage::Format_ARGB32);
    memcpy(m_lastFrame.bits(), videoFrame.bits(),videoFrame.mappedBytes() - 32);

    ...

} ...

Upvotes: 0

Views: 5523

Answers (2)

Rudolf Cardinal
Rudolf Cardinal

Reputation: 788

Since that doesn't always work, see also comment at convert QVideoFrame to QImage , i.e.

QImage Camera::imageFromVideoFrame(const QVideoFrame& buffer) const
{
    QImage img;
    QVideoFrame frame(buffer);  // make a copy we can call map (non-const) on
    frame.map(QAbstractVideoBuffer::ReadOnly);
    QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(
                frame.pixelFormat());
    // BUT the frame.pixelFormat() is QVideoFrame::Format_Jpeg, and this is
    // mapped to QImage::Format_Invalid by
    // QVideoFrame::imageFormatFromPixelFormat
    if (imageFormat != QImage::Format_Invalid) {
        img = QImage(frame.bits(),
                     frame.width(),
                     frame.height(),
                     // frame.bytesPerLine(),
                     imageFormat);
    } else {
        // e.g. JPEG
        int nbytes = frame.mappedBytes();
        img = QImage::fromData(frame.bits(), nbytes);
    }
    frame.unmap();
    return img;
}

Upvotes: 1

Alok
Alok

Reputation: 163

You can try creating a QImage by first mapping the QVideoFrame onto a QAbstractVideoBuffer in the following way :

bool CameraFrameGrabber::present(const QVideoFrame &frame)
{
Q_UNUSED(frame);
if (frame.isValid()) {
    QVideoFrame cloneFrame(frame);
    cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
    const QImage image(cloneFrame.bits(),
                       cloneFrame.width(),
                       cloneFrame.height(),
                      QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));


    emit frameAvailable(image);
    qDebug()<<cloneFrame.mappedBytes();
    cloneFrame.unmap();
    return true;
}

If you want QImage in any other format just change the last parameter during creating the image, to the whichever format you like :

QImage::Format_xxx ;

instead of

QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));

Upvotes: 0

Related Questions