Qt 如何将QVideoFrame转换为QImage

Qt 如何将QVideoFrame转换为QImage,qt,Qt,任务是从QVideoFrame复制一个帧,并可能对该图像执行某些操作,并在QML中显示处理后的图像 上面的代码会导致崩溃,因为m_lastFrame缺少32个字节(3686400对3686432) videoFrame.mappedBytes()报告3686432字节。我做错了什么?或者我应该如何计算m_lastFrame()的大小 该代码在Mac OSx 10.9.5 Qt 5.1.1上运行 一些附加代码: 。。。 if(videoFrame.映射(QAbstractVideoBuffer

任务是从QVideoFrame复制一个帧,并可能对该图像执行某些操作,并在QML中显示处理后的图像

上面的代码会导致崩溃,因为m_lastFrame缺少32个字节(3686400对3686432) videoFrame.mappedBytes()报告3686432字节。我做错了什么?或者我应该如何计算m_lastFrame()的大小

该代码在Mac OSx 10.9.5 Qt 5.1.1上运行

一些附加代码:

。。。 if(videoFrame.映射(QAbstractVideoBuffer::ReadOnly)){

}

您可以尝试通过以下方式首先将QVideoFrame映射到QAbstractVideoBuffer来创建QImage:

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;
}
bool-CameraFrameGrabber::present(const-QVideoFrame&frame)
{
Q_未使用(帧);
if(frame.isValid()){
QVideoFrame克隆帧(frame);
map(QAbstractVideoBuffer::ReadOnly);
常量图像(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat());
发射帧可用(图像);

qDebug()由于这并不总是有效,请参见的注释,即


您是否调用了
videoFrame.map(QAbstractVideoBuffer::ReadOnly)
并检查了返回值?您是否确定视频帧包含ARGB32数据?在调用
videoFrame.bits()之前,您是否成功地(通过调用
map()
)将视频帧的内容映射到系统内存
?在这种情况下,我认为应该通过将像素格式正确转换为图像格式来解决您的问题。是@njahnke。我正在调用map()根据上面的
好的,@mhcuervo。谢谢你们的宝贵意见。我检查了格式,它使用的格式正确。我将在pc上运行此代码,看看结果如何。在Windows 8上使用Qt 5.3.2进行了测试。两个函数都返回了3686400字节。因此,MAC上似乎存在问题。但是,发现了其他问题在PC上,返回的帧是颠倒的,RGB32图像只渲染了一个白色帧。转换为ARGB_32并渲染图像。下一步将使用一些日志来调查实际像素值。想法是在多个平台上使用它,到目前为止,Qt fw似乎无法提供良好的跨平台功能。您无法指定您喜欢的格式。它必须是您提供的数据的格式,因此需要
QVideoFrame::imageFormatFromPixelFormat
    m_lastFrame = QImage(videoFrame.width(),videoFrame.height(),QImage::Format_ARGB32);
    memcpy(m_lastFrame.bits(), videoFrame.bits(),videoFrame.mappedBytes() - 32);

    ...
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;
}
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;
}