2014-10-07 2 views
0

Я хочу сделать приложение для видеоконференций с QT. Я новичок в этом. Буду признателен, если у кого-нибудь есть пример.Использование QAbstractVideoSurface

Теперь я пытаюсь отобразить изображение камеры на экране, используя подкласс qabstractvideosurface. У кого-нибудь есть идея, как это сделать?

+0

Хороший вопрос должен указывать на некоторый уровень исследований ... Например, вы пытались найти любую связанную с ней документацию? Как говорится, вопрос кажется очень открытым. –

+0

Да, я боюсь уже месяц. Я использовал cameraviewfinder, который отображает только то, что видит камера. Чтобы получить видеодраймы, я, вероятно, должен использовать метод, упомянутый выше. Но в Интернете нет примеров, которые я мог бы попробовать. поблагодарить вас за ваш комментарий, это был мой первый вопрос, поэтому, пожалуйста, не слишком строги – lionlinekz

+0

@lionlinekz вы боретесь с реализацией подкласса или как использовать объект VideoSurface? – UmNyobe

ответ

12

QAbstractVideoSurface - это интерфейс между производителем и потребителем видеокадров. У вас есть только две функции для реализации, чтобы начать с:

  1. supportedPixelFormats так, что производитель может выбрать подходящий формат для QVideoFrame
  2. 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; 
    } 
} 

Этот пример, очевидно, не является оптимальным.

  1. Он не берет деньги за то, чтоможет храниться в видеопамяти, потому что мы рисуем с использованием pixmap.
  2. Преобразование изображения в растровое изображение является ненужным.

Вы можете написать собственный виджет и реализовать paintEvent для лучшей производительности. Кроме того, у вас есть несколько дизайнерских прав на поведение present(). Например:

  • Является ли неблокирующая поверхность, то есть рамка уже показана, когда она заканчивается. Выше это будет означать использование mylabel->repaint() вместо mylabel->update()
  • Что происходит, когда вы не можете завершить презентацию. Возможно, вам захочется нарисовать пустой кадр, а не возвращать ошибку, которая может остановить музыку.
+0

Большое вам спасибо, это мне очень помогло!Однако изображение, отображаемое на дисплее, является зеленым и пурпурным, любые предложения по его устранению? – lionlinekz

+0

'QVideoFrame :: Format_RGB24' может быть' QVideoFrame :: Format_BGR24'. Играйте с разными форматами rgb, которые вы должны сопоставить с вашим источником. – UmNyobe