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
107 stars 36 forks source link

Memory leak with Qt5.12 #13

Closed Inounx closed 8 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 8 months ago

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