Details
-
Bug
-
Resolution: Out of scope
-
P2: Important
-
None
-
6.7.3, 6.8.0, 6.8.1
-
None
-
Windows 10 21H2
Qt 6.7.3 6.8.0 6.8.1
NVDIA 1060 with 32.0.15.6094
-
-
Multimedia Next
Description
Create two pages, one is an empty page, and the other is a viewfinder page. When starting, the memory usage is very low. After switching to the viewfinder page, the memory usage becomes high, which is expected. When switching back to the empty page, the memory is expected to be released and return to low memory usage. However, the memory is not released at this time and is still high. I tried to delete it explicitly, but it didn't work.
Similarly, it's not just use QVideoSink::toImage on paintEvent. When using QVideoWidget, the memory is still not released, but the memory usage will be little lower.
For intuitive display, I drew a simple schematic diagram. See the attachment 1.png. Attachment 2 is the first launch of the program. You can see that the memory usage is only about 20mb. Attachment 3 is switching to the viewfinder page, which occupies about 200mb. This is expected because the resolution is very high. Attachment 4 is switching back to the empty page. The memory is not released and remains at 160-200mb.
#include <QApplication> #include <QCamera> #include <QCameraDevice> #include <QMediaCaptureSession> #include <QMediaDevices> #include <QPainter> #include <QPushButton> #include <QStackedWidget> #include <QVideoSink> #include <QVBoxLayout> #include <QWidget> class NormalPage : public QWidget { public: explicit NormalPage(QWidget* parent = nullptr) : QWidget(parent) {} }; class ViewfinderPage : public QWidget { public: explicit ViewfinderPage(QWidget* parent = nullptr) : QWidget(parent) { m_videoSink = new QVideoSink(this); connect(m_videoSink, &QVideoSink::videoFrameChanged, this, &ViewfinderPage::onFrameChanged); m_camera = new QCamera(QMediaDevices::defaultVideoInput()); m_session = new QMediaCaptureSession(this); m_session->setCamera(m_camera); m_session->setVideoOutput(m_videoSink); m_camera->start(); } protected: void paintEvent(QPaintEvent* event) override { QWidget::paintEvent(event); QPainter painter(this); if (m_currentFrame.isValid()) { painter.fillRect( rect(), m_currentFrame.toImage().scaled(rect().size(), Qt::KeepAspectRatio) ); } } private slots: void onFrameChanged(const QVideoFrame& frame) { m_currentFrame = frame; update(); } private: QVideoSink* m_videoSink; QCamera* m_camera; QMediaCaptureSession* m_session; QVideoFrame m_currentFrame; }; class Win : public QWidget { public: Win() { resize(800, 600); setWindowTitle("Memory Leak Test"); m_mainLayout = new QVBoxLayout(this); m_toggleButton = new QPushButton("Toggle Page"); connect(m_toggleButton, &QPushButton::clicked, this, &Win::togglePage); m_container = new QStackedWidget(); m_normalPage = new NormalPage(); m_viewfinderPage = new ViewfinderPage(); m_container->addWidget(m_normalPage); m_container->addWidget(m_viewfinderPage); m_mainLayout->addWidget(m_container); m_mainLayout->addWidget(m_toggleButton); } private slots: void togglePage() { m_container->setCurrentIndex(1 - m_container->currentIndex()); } private: QVBoxLayout* m_mainLayout; QPushButton* m_toggleButton; QStackedWidget* m_container; NormalPage* m_normalPage; ViewfinderPage* m_viewfinderPage; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); Win win; win.show(); return app.exec(); }