9

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;
}
mhcuervo
  • 2,610
  • 22
  • 33
Hasti Ranjkesh
  • 643
  • 10
  • 26
  • What is the resolution of your image? and you are doing it on an android? – user1767754 Sep 21 '14 at 11:42
  • Thank you for your replying. yes,I'm doing it on android. img size is: QSize(640, 480) – Hasti Ranjkesh Sep 21 '14 at 11:49
  • I've used QPainter and passed it a QImage / OPixmap and used painter.drawImage and painter.drawPixmap. but still camera frames are shown very slowly in QPainter. – Hasti Ranjkesh Sep 22 '14 at 10:27
  • Instead of using Qt's implementation, I have used [andrechen/yuv2rgb](https://github.com/andrechen/yuv2rgb) to convert NV12 to QImage. However, the conversion still uses a lot of CPU and is not sufficiently fast for real-time streaming. – Alex Spataru Dec 18 '16 at 15:25
  • Think you need video player widget instead QLabel. – stanislav888 Jan 26 '18 at 06:29

1 Answers1

1

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.

eSKon
  • 439
  • 3
  • 6