1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

New camera system, preparation for video

This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-06-29 23:41:47 +02:00
parent a2566d4183
commit 6ff776f345
9 changed files with 487 additions and 188 deletions

View File

@ -1,121 +1,125 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-06-22T14:07:35
#
#-------------------------------------------------
QT += core gui multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = toxgui
TEMPLATE = app
HEADERS += widget/form/addfriendform.h \
widget/form/chatform.h \
widget/form/groupchatform.h \
widget/form/settingsform.h \
widget/tool/chattextedit.h \
widget/tool/copyableelidelabel.h \
widget/tool/editablelabelwidget.h \
widget/tool/elidelabel.h \
widget/tool/esclineedit.h \
widget/tool/friendrequestdialog.h \
widget/filetransfertwidget.h \
widget/friendwidget.h \
widget/groupwidget.h \
widget/widget.h \
friend.h \
group.h \
grouplist.h \
settings.h \
status.h \
core.h \
friendlist.h \
cdata.h \
cstring.h \
audiobuffer.h \
widget/selfcamview.h
FORMS += widget.ui
CONFIG += c++11
RESOURCES += \
res.qrc
LIBS += -ltoxcore -ltoxav -lsodium
SOURCES += \
widget/form/addfriendform.cpp \
widget/form/chatform.cpp \
widget/form/groupchatform.cpp \
widget/form/settingsform.cpp \
widget/tool/chattextedit.cpp \
widget/tool/copyableelidelabel.cpp \
widget/tool/editablelabelwidget.cpp \
widget/tool/elidelabel.cpp \
widget/tool/esclineedit.cpp \
widget/tool/friendrequestdialog.cpp \
widget/filetransfertwidget.cpp \
widget/friendwidget.cpp \
widget/groupwidget.cpp \
widget/widget.cpp \
core.cpp \
friend.cpp \
friendlist.cpp \
group.cpp \
grouplist.cpp \
main.cpp \
settings.cpp \
status.cpp \
cdata.cpp \
cstring.cpp \
audiobuffer.cpp \
widget/selfcamview.cpp
### EXAMPLE BUILD SETTINGS FOR WINDOWS
#win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -ltoxcore
#INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/toxcore.lib
#else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libtoxcore.a
#win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -ltoxav
#INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/toxav.lib
#else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libtoxav.a
#win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lvpx
#INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/vpx.lib
#else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libvpx.a
#win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lopus
#INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/opus.lib
#else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libopus.a
#win32: LIBS += -lws2_32
#win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lsodium
#INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
#win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/sodium.lib
#else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libsodium.a
#-------------------------------------------------
#
# Project created by QtCreator 2014-06-22T14:07:35
#
#-------------------------------------------------
QT += core gui multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = toxgui
TEMPLATE = app
HEADERS += widget/form/addfriendform.h \
widget/form/chatform.h \
widget/form/groupchatform.h \
widget/form/settingsform.h \
widget/tool/chattextedit.h \
widget/tool/copyableelidelabel.h \
widget/tool/editablelabelwidget.h \
widget/tool/elidelabel.h \
widget/tool/esclineedit.h \
widget/tool/friendrequestdialog.h \
widget/filetransfertwidget.h \
widget/friendwidget.h \
widget/groupwidget.h \
widget/widget.h \
friend.h \
group.h \
grouplist.h \
settings.h \
status.h \
core.h \
friendlist.h \
cdata.h \
cstring.h \
audiobuffer.h \
widget/selfcamview.h \
widget/videosurface.h \
widget/camera.h
FORMS += widget.ui
CONFIG += c++11
RESOURCES += \
res.qrc
LIBS += -ltoxcore -ltoxav -lsodium -lvpx
SOURCES += \
widget/form/addfriendform.cpp \
widget/form/chatform.cpp \
widget/form/groupchatform.cpp \
widget/form/settingsform.cpp \
widget/tool/chattextedit.cpp \
widget/tool/copyableelidelabel.cpp \
widget/tool/editablelabelwidget.cpp \
widget/tool/elidelabel.cpp \
widget/tool/esclineedit.cpp \
widget/tool/friendrequestdialog.cpp \
widget/filetransfertwidget.cpp \
widget/friendwidget.cpp \
widget/groupwidget.cpp \
widget/widget.cpp \
core.cpp \
friend.cpp \
friendlist.cpp \
group.cpp \
grouplist.cpp \
main.cpp \
settings.cpp \
status.cpp \
cdata.cpp \
cstring.cpp \
audiobuffer.cpp \
widget/selfcamview.cpp \
widget/videosurface.cpp \
widget/camera.cpp
### EXAMPLE BUILD SETTINGS FOR WINDOWS
win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -ltoxcore
INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/toxcore.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libtoxcore.a
win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -ltoxav
INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/toxav.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libtoxav.a
win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lvpx
INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/vpx.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libvpx.a
win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lopus
INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/opus.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libopus.a
win32: LIBS += -lws2_32
win32: LIBS += -L$$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/ -lsodium
INCLUDEPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
DEPENDPATH += $$PWD/../../../../Downloads/libtoxcore-win32-i686/include
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/sodium.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../Downloads/libtoxcore-win32-i686/lib/libsodium.a

166
widget/camera.cpp Normal file
View File

@ -0,0 +1,166 @@
#include "camera.h"
#include <QVideoSurfaceFormat>
#include <QMessageBox>
Camera::Camera()
: refcount{0}, camera{new QCamera}
{
camera->setCaptureMode(QCamera::CaptureVideo);
camera->setViewfinder(this);
connect(camera, SIGNAL(error(QCamera::Error)), this, SLOT(onCameraError(QCamera::Error)));
supportedFormats << QVideoFrame::Format_YUV420P << QVideoFrame::Format_YV12 << QVideoFrame::Format_RGB32;
}
void Camera::suscribe()
{
if (refcount <= 0)
{
refcount = 1;
camera->start();
}
else
refcount++;
}
void Camera::unsuscribe()
{
refcount--;
if (refcount <= 0)
{
camera->stop();
refcount = 0;
}
}
QVideoFrame Camera::getLastFrame()
{
return lastFrame;
}
bool Camera::start(const QVideoSurfaceFormat &format)
{
if(supportedFormats.contains(format.pixelFormat()))
{
frameFormat = format.pixelFormat();
QAbstractVideoSurface::start(format);
return true;
}
else
{
QMessageBox::warning(0, "Camera error", "The camera only supports rare video formats, can't use it");
return false;
}
}
bool Camera::present(const QVideoFrame &frame)
{
QVideoFrame frameMap(frame); // Basically a const_cast because shallow copies
frameMap.map(QAbstractVideoBuffer::ReadOnly);
int w = frameMap.width(), h = frameMap.height();
int bpl = frameMap.bytesPerLine(), size = frameMap.mappedBytes();
QVideoFrame frameCopy(size, QSize(w, h), bpl, frameMap.pixelFormat());
frameCopy.map(QAbstractVideoBuffer::WriteOnly);
memcpy(frameCopy.bits(), frameMap.bits(), size);
frameCopy.unmap();
lastFrame = frameCopy;
frameMap.unmap();
return true;
}
QList<QVideoFrame::PixelFormat> Camera::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle)
return supportedFormats;
else
return QList<QVideoFrame::PixelFormat>();
}
void Camera::onCameraError(QCamera::Error value)
{
QMessageBox::warning(0,"Camera error",QString("Error %1 : %2")
.arg(value).arg(camera->errorString()));
}
bool Camera::isFormatSupported(const QVideoSurfaceFormat& format) const
{
if (format.pixelFormat() == 0)
{
//QMessageBox::warning(0, "Camera eror","The camera's video format is not supported !");
return QAbstractVideoSurface::isFormatSupported(format);
}
else if(supportedFormats.contains(format.pixelFormat()))
{
return true;
}
else
{
QMessageBox::warning(0, "Camera eror",
QString("Camera format %1 not supported, can't use the camera")
.arg(format.pixelFormat()));
return false;
}
}
QImage Camera::getLastImage()
{
lastFrame.map(QAbstractVideoBuffer::ReadOnly);
int w = lastFrame.width(), h = lastFrame.height();
int bpl = lastFrame.bytesPerLine(), cxbpl = bpl/2;
QImage img(w, h, QImage::Format_RGB32);
if (frameFormat == QVideoFrame::Format_YUV420P)
{
uint8_t* yData = lastFrame.bits();
uint8_t* uData = yData + (bpl * h);
uint8_t* vData = uData + (bpl * h / 4);
for (int i = 0; i< h; i++)
{
uint32_t* scanline = (uint32_t*)img.scanLine(i);
for (int j=0; j < bpl; j++)
{
float Y = yData[i*bpl + j];
float U = uData[i*cxbpl/2 + j/2];
float V = vData[i*cxbpl/2 + j/2];
uint8_t R = qMax(qMin((int)(Y + 1.402 * (V - 128)),255),0);
uint8_t G = qMax(qMin((int)(Y - 0.344 * (U - 128) - 0.714 * (V - 128)),255),0);
uint8_t B = qMax(qMin((int)(Y + 1.772 * (U - 128)),255),0);
scanline[j] = (0xFF<<24) + (R<<16) + (G<<8) + B;
}
}
}
else if (frameFormat == QVideoFrame::Format_YV12)
{
uint8_t* yData = lastFrame.bits();
uint8_t* vData = yData + (bpl * h);
uint8_t* uData = vData + (bpl * h / 4);
for (int i = 0; i< h; i++)
{
uint32_t* scanline = (uint32_t*)img.scanLine(i);
for (int j=0; j < bpl; j++)
{
float Y = yData[i*bpl + j];
float U = uData[i*cxbpl/2 + j/2];
float V = vData[i*cxbpl/2 + j/2];
uint8_t R = qMax(qMin((int)(Y + 1.402 * (V - 128)),255),0);
uint8_t G = qMax(qMin((int)(Y - 0.344 * (U - 128) - 0.714 * (V - 128)),255),0);
uint8_t B = qMax(qMin((int)(Y + 1.772 * (U - 128)),255),0);
scanline[j] = (0xFF<<24) + (R<<16) + (G<<8) + B;
}
}
}
else if (frameFormat == QVideoFrame::Format_RGB32)
{
memcpy(img.bits(), lastFrame.bits(), bpl*h);
}
lastFrame.unmap();
return img;
}

47
widget/camera.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef CAMERA_H
#define CAMERA_H
#include <QCamera>
#include <QVideoFrame>
#include <QAbstractVideoSurface>
#include "vpx/vpx_image.h"
/**
* This class is a wrapper to share a camera's captured video frames
* In Qt cameras normally only send their frames to a single output at a time
* So you can't, for example, send the frames over the network
* and output them to a widget on the screen at the same time
*
* Instead this class allows objects to surscribe and unsuscribe, starting
* the camera only when needed, and giving access to the last frame
**/
class Camera : private QAbstractVideoSurface
{
Q_OBJECT
public:
Camera();
void suscribe(); ///< Call this once before trying to get frames
void unsuscribe(); ///< Call this once when you don't need frames anymore
QVideoFrame getLastFrame(); ///< Get the last captured frame
QImage getLastImage(); ///< Convert the last frame to a QImage (can be expensive !)
vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !)
bool isFormatSupported(const QVideoSurfaceFormat & format) const;
private slots:
void onCameraError(QCamera::Error value);
private:
bool start(const QVideoSurfaceFormat &format);
bool present(const QVideoFrame &frame);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
private:
int refcount; ///< Number of users suscribed to the camera
QCamera *camera;
QVideoFrame lastFrame;
int frameFormat;
QList<QVideoFrame::PixelFormat> supportedFormats;
};
#endif // CAMERA_H

View File

@ -1,4 +1,5 @@
#include "settingsform.h"
#include "widget/widget.h"
#include <QFont>
SettingsForm::SettingsForm()
@ -17,7 +18,6 @@ SettingsForm::SettingsForm()
id.setFont(small);
id.setTextInteractionFlags(Qt::TextSelectableByMouse);
camview = new SelfCamView();
videoTest.setText("Test video");
main->setLayout(&layout);
@ -38,7 +38,6 @@ SettingsForm::SettingsForm()
SettingsForm::~SettingsForm()
{
delete camview;
}
void SettingsForm::setFriendAddress(const QString& friendAddress)
@ -58,5 +57,5 @@ void SettingsForm::show(Ui::Widget &ui)
void SettingsForm::onTestVideoClicked()
{
camview->show();
Widget::getInstance()->showTestCamview();
}

View File

@ -30,7 +30,6 @@ private:
QPushButton videoTest;
QVBoxLayout layout, headLayout;
QWidget *main, *head;
SelfCamView* camview;
public:
QLineEdit name, statusText;

View File

@ -3,78 +3,49 @@
#include <QMessageBox>
#include <QCloseEvent>
#include <QShowEvent>
#include <QVideoFrame>
SelfCamView::SelfCamView(QWidget* parent)
: QWidget(parent), camera(nullptr), mainLayout{new QHBoxLayout()}
#include "videosurface.h"
#include "widget.h"
SelfCamView::SelfCamView(Camera* Cam, QWidget* parent)
: QWidget(parent), displayLabel{new QLabel},
mainLayout{new QHBoxLayout()}, cam(Cam)
{
setLayout(mainLayout);
setWindowTitle("Tox video test");
setMinimumSize(320,240);
QByteArray cameraDevice;
updateDisplayTimer.setInterval(75);
updateDisplayTimer.setSingleShot(false);
/*
QActionGroup *videoDevicesGroup = new QActionGroup(this);
videoDevicesGroup->setExclusive(true);
foreach(const QByteArray &deviceName, QCamera::availableDevices()) {
QString description = camera->deviceDescription(deviceName);
QAction *videoDeviceAction = new QAction(description, videoDevicesGroup);
videoDeviceAction->setCheckable(true);
videoDeviceAction->setData(QVariant(deviceName));
if (cameraDevice.isEmpty()) {
cameraDevice = deviceName;
videoDeviceAction->setChecked(true);
}
ui->menuDevices->addAction(videoDeviceAction);
}
displayLabel->setScaledContents(true);
connect(videoDevicesGroup, SIGNAL(triggered(QAction*)), SLOT(updateCameraDevice(QAction*)));
*/
mainLayout->addWidget(displayLabel);
viewfinder = new QCameraViewfinder(this);
mainLayout->addWidget(viewfinder);
viewfinder->show();
setCamera(cameraDevice);
connect(&updateDisplayTimer, SIGNAL(timeout()), this, SLOT(updateDisplay()));
}
SelfCamView::~SelfCamView()
{
delete camera;
}
void SelfCamView::setCamera(const QByteArray &cameraDevice)
{
delete camera;
if (cameraDevice.isEmpty())
camera = new QCamera;
else
camera = new QCamera(cameraDevice);
//connect(camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(updateCameraState(QCamera::State)));
connect(camera, SIGNAL(error(QCamera::Error)), this, SLOT(displayCameraError()));
camera->setViewfinder(viewfinder);
//updateCameraState(camera->state());
camera->setCaptureMode(QCamera::CaptureVideo);
}
void SelfCamView::displayCameraError()
{
QMessageBox::warning(this, tr("Camera error"), camera->errorString());
}
void SelfCamView::closeEvent(QCloseEvent* event)
{
camera->stop();
cam->unsuscribe();
updateDisplayTimer.stop();
event->accept();
}
void SelfCamView::showEvent(QShowEvent* event)
{
camera->start();
cam->suscribe();
updateDisplayTimer.start();
event->accept();
}
void SelfCamView::updateDisplay()
{
displayLabel->setPixmap(QPixmap::fromImage(cam->getLastImage()));
}

View File

@ -1,37 +1,37 @@
#ifndef SELFCAMVIEW_H
#define SELFCAMVIEW_H
#include <QCamera>
#include <QCameraImageCapture>
#include <QMediaRecorder>
#include <QWidget>
#include <QVideoWidget>
#include <QCameraViewfinder>
#include <QHBoxLayout>
#include <QTimer>
#include <QLabel>
#include "camera.h"
class QCloseEvent;
class QShowEvent;
class QPainter;
class SelfCamView : public QWidget
{
Q_OBJECT
public:
SelfCamView(QWidget *parent=0);
SelfCamView(Camera* Cam, QWidget *parent=0);
~SelfCamView();
private slots:
void updateDisplay();
private:
void closeEvent(QCloseEvent*);
void showEvent(QShowEvent*);
private slots:
void setCamera(const QByteArray &cameraDevice);
void displayCameraError();
void paint(QPainter *painter);
private:
QCamera *camera;
QCameraViewfinder* viewfinder;
QLabel *displayLabel;
QHBoxLayout* mainLayout;
Camera* cam;
QTimer updateDisplayTimer;
};
#endif // SELFCAMVIEW_H

87
widget/videosurface.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "videosurface.h"
#include "core.h"
#include <QVideoFrame>
#include <QDebug>
VideoSurface::VideoSurface()
: QAbstractVideoSurface()
{
vpx_img_alloc(&input, VPX_IMG_FMT_YV12, TOXAV_VIDEO_WIDTH, TOXAV_VIDEO_HEIGHT, 1);
}
bool VideoSurface::start(const QVideoSurfaceFormat &format)
{
mVideoFormat = format;
//start only if format is UYVY, dont handle other format now
if( format.pixelFormat() == QVideoFrame::Format_YV12 ){
QAbstractVideoSurface::start(format);
return true;
} else {
return false;
}
}
bool VideoSurface::present(const QVideoFrame &frame)
{
/*
mFrame = frame;
qDebug() << QString("Video: Frame format is %1").arg(mFrame.pixelFormat());
stop();
//this is necessary to get valid data from frame
mFrame.map(QAbstractVideoBuffer::ReadOnly);
uchar* data = new uchar[frame.mappedBytes()];
memcpy(data, frame.bits(), frame.mappedBytes());
input.planes[VPX_PLANE_Y] = data;
input.planes[VPX_PLANE_U] = data + (frame.bytesPerLine() * frame.height());
input.planes[VPX_PLANE_V] = input.planes[VPX_PLANE_U] + (frame.bytesPerLine()/2 * frame.height()/2);
input.planes[VPX_PLANE_ALPHA] = nullptr;
//qDebug() << QString("Got %1 bytes, first plane is %2 bytes long")
// .arg(frame.mappedBytes()).arg(frame.bytesPerLine() * frame.height());
// Slots MUST be called with a direct or blocking connection, or input may die before they return !
emit videoFrameReady(input);
QImage lastImage( mFrame.size(), QImage::Format_RGB16);
const uchar *src = mFrame.bits();
uchar *dst = lastImage.bits();
const int srcLineStep = mFrame.bytesPerLine();
const int dstLineStep = lastImage.bytesPerLine();
const int h = mFrame.height();
const int w = mFrame.width();
for (int y=0; y < h; y++) {
//this function you can find in qgraphicsvideoitem_maemo5.cpp,
//link is mentioned above
uyvy422_to_rgb16_line_neon(dst, src, w);
src += srcLineStep;
dst += dstLineStep;
}
mLastFrame = QPixmap::fromImage(lastImage);
//emit signal, other can handle it and do necessary processing
emit frameUpdated(mLastFrame);
delete[] data;
mFrame.unmap();
*/
return true;
}
QList<QVideoFrame::PixelFormat> VideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle) {
qDebug() << "Video: No handle";
return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_YV12;
} else {
qDebug() << "Video: Handle type is not NoHandle";
return QList<QVideoFrame::PixelFormat>();
}
}

26
widget/videosurface.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef VIDEOSURFACE_H
#define VIDEOSURFACE_H
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include "vpx/vpx_image.h"
class VideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
public:
VideoSurface();
bool start(const QVideoSurfaceFormat &format);
bool present(const QVideoFrame &frame);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
signals:
// Slots MUST be called with a direct or blocking connection, or img may die before they return !
void videoFrameReady(vpx_image img);
private:
QVideoSurfaceFormat mVideoFormat;
vpx_image_t input;
};
#endif // VIDEOSURFACE_H