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;
}
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With