scytheStudio / SCodes

This project is Qt & Qml wrapper for ZXing-C++ Library that is used for decoding 1D and 2D barcodes.
https://scythe-studio.com/
Apache License 2.0
114 stars 38 forks source link

Memory leak with Qt5.12 #13

Closed Inounx closed 11 months ago

Inounx commented 2 years ago

Hi, I am trying your wrapper with Qt5.12, and encountered a memory leak. This is due to imageFromVideoFrame() in SBarcodeDecoder.cpp (Line 188) There is memory allocated for the frame to be copied, but QImage do not take ownership of the memory, so it is never released. QImage provides a handler mecanism, intended to free the memory when the last intance of QImage using this memory is destroyed. You need to create the handler to cleanup the memory, and provide it to the QImage when creating it, with the pointer to the memory. Also, the memory must be allocated only when it is need, i.e. when imageFormat == QImage::Format_Invalid Here is the modified code :

void imageCleanupHandler(void *info)
{
    delete[] (uchar*)info;
}

QImage SBarcodeDecoder::imageFromVideoFrame(const QVideoFrame &videoFrame)
{
    QImage::Format imageFormat = videoFrame.imageFormatFromPixelFormat(videoFrame.pixelFormat());
    if(imageFormat == QImage::Format_Invalid){
        uchar* ARGB32Bits = new uchar[(videoFrame.width() * videoFrame.height()) * 4];
        switch(videoFrame.pixelFormat()){
            case QVideoFrame::Format_YUYV: qt_convert_YUYV_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_NV12: qt_convert_NV12_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_YUV420P: qt_convert_YUV420P_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_YV12: qt_convert_YV12_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_AYUV444: qt_convert_AYUV444_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_YUV444: qt_convert_YUV444_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_UYVY: qt_convert_UYVY_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_NV21: qt_convert_NV21_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_BGRA32: qt_convert_BGRA32_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_BGR24: qt_convert_BGR24_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_BGR565: qt_convert_BGR565_to_ARGB32(videoFrame, ARGB32Bits); break;
            case QVideoFrame::Format_BGR555: qt_convert_BGR555_to_ARGB32(videoFrame, ARGB32Bits); break;
            default: break;
        }

        return QImage(ARGB32Bits,
                      videoFrame.width(),
                      videoFrame.height(),
                      QImage::Format_ARGB32,
                      imageCleanupHandler,
                      ARGB32Bits);
    }

    return QImage(videoFrame.bits(),
                  videoFrame.width(),
                  videoFrame.height(),
                  imageFormat);
}

These modifications solve the memory leak problem for me. Sorry I don't have the time to create a proper PR, but I thought it might be usefull for others.

BartoszSkorka commented 11 months ago

I'm closing this issue as it no longer applies.