Я пытаюсь отобразить изображение с камеры на экране, используя подкласс QAbstractVideoSurface, и у меня нет в этом опыта.
Буду признателен, если кто-нибудь объяснит, как это сделать.
Я пытаюсь отобразить изображение с камеры на экране, используя подкласс QAbstractVideoSurface, и у меня нет в этом опыта.
Буду признателен, если кто-нибудь объяснит, как это сделать.
QAbstractVideoSurface
— это интерфейс между производителем и потребителем видеокадров. Для начала у вас есть только две функции:
QVideoFrame
Допустим, вы хотите использовать классический QWidget
для отображения. В этом случае вы можете использовать QImage
для рисования виджета.
Первый Qt гарантированно рисует QImage
, который является 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
может храниться в видеопамяти, не требует денег, потому что мы рисуем с помощью растрового изображения.Вы можете написать свой собственный виджет и реализовать paintEvent для повышения производительности. Кроме того, у вас есть несколько дизайнерских вольностей в отношении поведения present()
. Например :
mylabel->repaint()
вместо mylabel->update()
QVideoFrame::Format_RGB24
может быть QVideoFrame::Format_BGR24
. Поиграйте с различными форматами rgb, чтобы они соответствовали вашему источнику.
- person UmNyobe; 08.10.2014