我正在尝试使用QAbstractVideoSurface子类在屏幕上显示相机图片,但我对此没有经验。如果有人能够解释如何做到这一点,我将不胜感激。
QAbstractVideoSurface
是视频帧生产者和消费者之间的接口。您需要实现以下两个函数:
QVideoFrame
选择适当的格式。假设您想要在经典的QWidget
上显示。在这种情况下,您可以选择使用QImage
来绘制小部件。
首先,在大多数平台上,Qt保证会对RGB24(或BGR24)进行绘制。
QList<QVideoFrame::PixelFormat> LabelBasedVideoSurface::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle) {
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_RGB24;
} else {
return QList<QVideoFrame::PixelFormat>();
}
}
现在要呈现QVideoFrame,您需要将其数据映射到QImage,并将QImage绘制到小部件上。出于简单起见,我将使用一个 QLabel
,直接访问它(没有信号没有槽)。
bool LabelBasedVideoSurface::present(const QVideoFrame &frame)
{
if (notMyFormat(frame.pixelFormat())) {
setError(IncorrectFormatError);
return false;
} else {
QVideoFrame frametodraw(frame);
if(!frametodraw.map(QAbstractVideoBuffer::ReadOnly))
{
setError(ResourceError);
return false;
}
//this is a shallow operation. it just refer the frame buffer
QImage image(
frametodraw.bits(),
frametodraw.width(),
frametodraw.height(),
frametodraw.bytesPerLine(),
QImage::Format_RGB444);
mylabel->resize(image.size());
//QPixmap::fromImage create a new buffer for the pixmap
mylabel->setPixmap(QPixmap::fromImage(image));
//we can release the data
frametodraw.unmap();
mylabel->update();
return true;
}
}
这个示例显然不是最优的。
QVideoFrame
可能存储在视频内存中,因为我们使用了 pixmap 进行绘制。你可以编写自己的小部件,并实现一个 paintEvent 以获得更好的性能。此外,在 present()
函数的行为上,你有几种设计自由度。例如:
mylabel->repaint()
而不是 mylabel->update()
QVideoFrame::Format_RGB24
可能是 QVideoFrame::Format_BGR24
。尝试使用不同的 RGB 格式来匹配您的源。 - UmNyobe