Qt: непрерывный захват изображений с камеры заполняет память - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь непрерывно захватывать изображения, чтобы отправлять их по протоколу UDP.Я делаю это для реализации программы потокового видео в реальном времени.

Приведенный ниже код непрерывно захватывает изображения и присваивает изображения QGraphicsScene, чтобы я мог проверить, воспроизводятся ли изображения как видео.Но когда я запускаю программу, мой компьютер зависает через пару секунд, хотя я удаляю указатели.Как я могу решить эту проблему?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
cam = new QCamera;
cam->setCaptureMode(QCamera::CaptureStillImage);

viewfinder = new QCameraViewfinder;
viewfinder->show();
QCameraImageCapture *cap = new QCameraImageCapture(cam);
cap->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);

cam->setViewfinder(viewfinder);


QObject::connect(cap, &QCameraImageCapture::imageCaptured, [=] (int id, QImage img) {

     while(true){
        QByteArray *buf = new QByteArray;
        QBuffer *buffer=new QBuffer(buf);
        buffer->open(QIODevice::WriteOnly);
        img.save(buffer, "BMP");
        QPixmap *pixmap = new QPixmap();
        pixmap->loadFromData(buffer->buffer());
        scene->addPixmap(*pixmap);
        delete buf;
        delete buffer;
        delete pixmap;

        QThread::sleep(0.0416);
        cap->capture();

     }

});

QObject::connect(cap, &QCameraImageCapture::readyForCaptureChanged, [=] (bool state) {
   if(state == true) {
       cam->searchAndLock();
       cap->capture();
       cam->unlock();
   }
});
cam->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Вы должны использовать imageAvailable () вместо сигнала imageCaptured.

Вот пример:

connect(cap, &QCameraImageCapture::imageAvailable, [=] (int id, QVideoFrame v ) {

    if (v.isValid()) {
        if(v.map(QAbstractVideoBuffer::ReadOnly)) {

            QByteArray bitsVideo( (char *) v.bits(), v.mappedBytes() );

            //call to your send raw data function (over UDP) : 
            //datagram will contain frame details e.g : [ width, hight, byteperline, format, rawdata ]

            sendDataOverUDP( v.width(), v.height(), 
                             v.bytesperLine(), 
                             QVideoFrame::imageFormatFromPixelFormat(v.pixelFormat()), 
                             bitsVideo );


        }
    }
});

Другая сторона, сервер или другие клиенты будут создавать образ из необработанных данных, полученных следующим образом:

    void onDataImageReceived( int width, int height, 
                          int bytePerLine, 
                          QImage::Format fmt, 
                          QByteArray bitsVideo )
{

    QImage img ((uchar *)bitsVideo.data(), width, height, bytesPerLine, fmt);
    //do something with img ...

}
0 голосов
/ 16 декабря 2018

Я не знаком с QCamera и родственными классами, но lambda, к которому вы подключаете сигнал QCameraImageCapture::imageCaptured, выглядит неправильно.Этот сигнал испускается, когда один кадр готов для предварительного просмотра.Однако в вашем lambda есть ...

while(true){
    QByteArray *buf = new QByteArray;
    QBuffer *buffer=new QBuffer(buf);
    buffer->open(QIODevice::WriteOnly);
    img.save(buffer, "BMP");
    QPixmap *pixmap = new QPixmap();
    pixmap->loadFromData(buffer->buffer());
    scene->addPixmap(*pixmap);
    delete buf;
    delete buffer;
    delete pixmap;

    QThread::sleep(0.0416);
    cap->capture();
}

Этот цикл while никогда не завершается и блокирует цикл обработки событий Qt.Также обратите внимание, что фрагмент кода ...

QByteArray *buf = new QByteArray;
QBuffer *buffer=new QBuffer(buf);
buffer->open(QIODevice::WriteOnly);
img.save(buffer, "BMP");
QPixmap *pixmap = new QPixmap();
pixmap->loadFromData(buffer->buffer());
scene->addPixmap(*pixmap);
delete buf;
delete buffer;
delete pixmap;

является избыточным и (если я не ошибаюсь) в основном составляет ...

scene->addPixmap(QPixmap::fromImage(img));

Так что я думаю, что ваш lambda должно быть больше похоже (не проверено) ...

[=](int id, QImage img)
{
    scene->addPixmap(QPixmap::fromImage(img));
}
...