Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-132117

Memory never release when using QVideoSink QVideoWidget QVideoFrame

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • P2: Important
    • None
    • 6.7.3, 6.8.0, 6.8.1
    • Multimedia
    • None
    • Windows 10 21H2
      Qt 6.7.3 6.8.0 6.8.1
      NVDIA 1060 with 32.0.15.6094
    • Windows
    • 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();
      }
      
      

      Attachments

        1. 1.png
          1.png
          60 kB
        2. 2.png
          2.png
          81 kB
        3. 3.png
          3.png
          735 kB
        4. 4.png
          4.png
          83 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            qtmultimediateam Qt Multimedia Team
            rainzee rainzee wang
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes