2014-12-04 275 views
0

任務是從QVideoFrame複製幀,並可能對該圖像執行某些操作並在QML中顯示操縱的圖像。如何將QVideoFrame轉換爲QImage

...

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

...

上面的代碼會導致系統崩潰,因爲m_lastFrame是短的32個字節(3686400 VS 3686432) videoFrame.mappedBytes()報告3686432個字節。我在這裏做錯了什麼?或者我應該如何計算m_lastFrame()的大小。

該代碼在Mac OS X 10.9.5 Qt 5.1.1上運行。

一些額外的代碼:

... 如果(videoFrame 地圖(QAbstractVideoBuffer ::只讀)){

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

    ... 

} ...

+0

你打電話'videoFrame.map(QAbstractVideoBuffer ::只讀)'和檢查返回值?你確定視頻幀包含ARGB32數據嗎? – njahnke 2014-12-04 16:15:52

+0

在調用'videoFrame.bits()'之前,您是否已成功將視頻幀的內容映射到系統內存(調用'map()')?在這種情況下,我認爲你的問題應該通過將像素格式正確轉換爲圖像格式來解決。 – mhcuervo 2014-12-04 16:21:27

+0

是@njahnke。我正在根據上面的
2014-12-05 10:42:00

回答

0

你可以試試首先通過以下方式將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; 
} 

如果您在任何其他格式要QImage的只是創建圖像期間改變的最後一個參數,到哪個格式你喜歡:

的QImage :: Format_xxx;

代替

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

+0

你不能只指定你喜歡的格式。它必須是您提供的數據格式,因此需要'QVideoFrame :: imageFormatFromPixelFormat'。 – 2017-07-13 08:34:34

0

因爲這並不總是有效,又見於convert QVideoFrame to QImage評論,即

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