QAbstractVideoSurface
- это интерфейс между производителем и потребителем видеокадров. У вас есть только две функции для реализации, чтобы начать с:
- supportedPixelFormats так, что производитель может выбрать подходящий формат для
QVideoFrame
- present который более общий формулировку шоу \ отображения этого кадра
Допустим, вы хотите использовать классический 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;
}
}
Этот пример, очевидно, не является оптимальным.
- Он не берет деньги за то, чтоможет храниться в видеопамяти, потому что мы рисуем с использованием pixmap.
- Преобразование изображения в растровое изображение является ненужным.
Вы можете написать собственный виджет и реализовать paintEvent для лучшей производительности. Кроме того, у вас есть несколько дизайнерских прав на поведение present()
. Например:
- Является ли неблокирующая поверхность, то есть рамка уже показана, когда она заканчивается. Выше это будет означать использование
mylabel->repaint()
вместо mylabel->update()
- Что происходит, когда вы не можете завершить презентацию. Возможно, вам захочется нарисовать пустой кадр, а не возвращать ошибку, которая может остановить музыку.
Хороший вопрос должен указывать на некоторый уровень исследований ... Например, вы пытались найти любую связанную с ней документацию? Как говорится, вопрос кажется очень открытым. –
Да, я боюсь уже месяц. Я использовал cameraviewfinder, который отображает только то, что видит камера. Чтобы получить видеодраймы, я, вероятно, должен использовать метод, упомянутый выше. Но в Интернете нет примеров, которые я мог бы попробовать. поблагодарить вас за ваш комментарий, это был мой первый вопрос, поэтому, пожалуйста, не слишком строги – lionlinekz
@lionlinekz вы боретесь с реализацией подкласса или как использовать объект VideoSurface? – UmNyobe