Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert QVideoFrame straight to QPixmap

I've used QVideoProbe to access camera frames. My platform is Android. I've converted each camera frames to QImage and then pixmap and show on QLabel. My problem is this process is very slow. frames are shown very slowly. Can I convert QVideoFrame straight to QPixmap or other faster way to showing camera frames? here is my code:

    QCamera *camera = new QCamera(this);

    camera->setCaptureMode(QCamera::CaptureViewfinder);

    QVideoProbe *videoProbe = new QVideoProbe(this);

    bool ret = videoProbe->setSource(camera);
    qDebug() <<"videoProbe->setSource(camera):" << ret;

    if (ret) {
          connect(videoProbe, SIGNAL(videoFrameProbed(const QVideoFrame &)),
                this, SLOT(present(const QVideoFrame &)));

    }

    camera->start();
...
...


bool MainWindow::present(const QVideoFrame &frame)
{
    qDebug() <<"counter:" << ++counter;

    QVideoFrame cloneFrame(frame);
    if(cloneFrame.map(QAbstractVideoBuffer::ReadOnly))
    {
        QImage img(
                cloneFrame.size(), QImage::Format_ARGB32);
                qt_convert_NV21_to_ARGB32(cloneFrame.bits(),
                (quint32 *)img.bits(),
                cloneFrame.width(),
                cloneFrame.height());

        label->setPixmap(QPixmap::fromImage(img));

        cloneFrame.unmap();
    }

    return true;
}
like image 683
Hasti Ranjkesh Avatar asked Sep 21 '14 10:09

Hasti Ranjkesh


1 Answers

1. To convert from video frame to QImage i use qt internal method:

//Somewhere before using
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
    ...
//using
QImage imgbuf=qt_imageFromVideoFrame(frame);
  1. You need skip some frames and show only some. It will allow you handle stream in maximal possible speed. I do that with following code:

    void MyVideoHandler::videoFrameProbed(const QVideoFrame &frame)
    {
        if(!started)
            return;
        if(!frameProcessor)
            return;
        if(m_isBusy)
        {
            //qDebug() << "Video frame dropped";
            return;
        }
        m_isBusy = true;
        qDebug() << "videoFrameProbed";
        QMetaObject::invokeMethod(frameProcessor, "processFrame", Qt::QueuedConnection,
            Q_ARG(QVideoFrame, frame),
            Q_ARG(bool, param1),
            Q_ARG(bool, param2),
            Q_ARG(bool, param3),
            Q_ARG(bool, param4));
        //qDebug() << "processFrame invoked";
    }
    

I'm calling it through invokeMethod just because frameProcessor lives in different thread, but it's not your case, because you need show it in UI thread.On other hand you could make conversion to QImage (or QPixmap) in thread and then send result to UI thread. So here is code how to do that:

frameProcessor=new MyVideoFrameProcessor();
frameProcessor->moveToThread(&videoStreamThread);

Ah, also i must say MyVideoFrameProcessor generates event on finishing processing and MyVideoHandler switches m_isBusy to false on it.

like image 168
eSKon Avatar answered Oct 12 '22 02:10

eSKon