mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
[ #12150 ] Fix video preview for higher resolutions
This commit is contained in:
@ -12,7 +12,7 @@ INCLUDE( ${LOCAL_CMAKE_MODULE_PATH}/TargetDistclean.cmake REQUIRED)
|
||||
|
||||
FIND_PACKAGE ( KdepimLibs REQUIRED )
|
||||
FIND_PACKAGE ( KDE4 REQUIRED )
|
||||
FIND_PACKAGE ( Qt4 REQUIRED QtCore QtGui QtXml QtDBus QtTest QtSVG QT_USE_QT* )
|
||||
FIND_PACKAGE ( Qt4 REQUIRED QtCore QtGui QtXml QtDBus QtTest QtSVG QtOpenGl QT_USE_QT* )
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
|
||||
|
@ -54,6 +54,7 @@ SET(
|
||||
widgets/CategoryDrawer.cpp
|
||||
widgets/CategorizedTreeWidget.cpp
|
||||
widgets/VideoWidget.cpp
|
||||
widgets/AcceleratedVideoWidget.cpp
|
||||
Codec.cpp
|
||||
CallView.cpp
|
||||
)
|
||||
@ -92,7 +93,7 @@ QT4_ADD_DBUS_INTERFACES(sflphone_client_kde_SRCS ${KDE4_DBUS_INTERFACES_DIR}/org
|
||||
|
||||
KDE4_ADD_EXECUTABLE(sflphone-client-kde ${sflphone_client_kde_SRCS} ${QtApp_RCC_SRCS})
|
||||
|
||||
TARGET_LINK_LIBRARIES(sflphone-client-kde ksflphone qtsflphone ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDEPIMLIBS_AKONADI_KMIME_LIBS} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_CONTACT_LIBS})
|
||||
TARGET_LINK_LIBRARIES(sflphone-client-kde ksflphone qtsflphone ${KDE4_KDEUI_LIBS} ${QT_QTOPENGL_LIBRARY} ${KDE4_KIO_LIBS} ${KDEPIMLIBS_AKONADI_KMIME_LIBS} ${KDEPIMLIBS_AKONADI_LIBS} ${KDEPIMLIBS_AKONADI_CONTACT_LIBS})
|
||||
|
||||
########### install files ###############
|
||||
|
||||
|
@ -106,7 +106,14 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="VideoWidget" name="m_pPreviewGV"/>
|
||||
<widget class="VideoWidget" name="m_pPreviewGV" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="m_pPreviewPB">
|
||||
@ -134,13 +141,13 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<customwidget>
|
||||
<class>VideoWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">widgets/VideoWidget.h</header>
|
||||
<header>widgets/VideoWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -27,10 +27,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
//Qt
|
||||
#include <QSharedMemory>
|
||||
#include <QDBusPendingReply>
|
||||
|
||||
//SFLPhone
|
||||
#include "video_interface_singleton.h"
|
||||
#include "VideoDevice.h"
|
||||
@ -39,15 +35,15 @@
|
||||
VideoModel* VideoModel::m_spInstance = NULL;
|
||||
|
||||
///Shared memory object
|
||||
typedef struct {
|
||||
struct SHMHeader {
|
||||
sem_t notification;
|
||||
sem_t mutex;
|
||||
|
||||
unsigned m_BufferGen;
|
||||
int m_BufferSize;
|
||||
|
||||
char data[0];
|
||||
} SHMHeader;
|
||||
char m_Data[0];
|
||||
};
|
||||
|
||||
|
||||
///Manage shared memory and convert it to QByteArray
|
||||
@ -85,7 +81,7 @@ class VideoRenderer {
|
||||
bool startShm ();
|
||||
|
||||
//Getters
|
||||
QByteArray renderToBitmap(bool& ok);
|
||||
QByteArray renderToBitmap(QByteArray& data, bool& ok);
|
||||
};
|
||||
|
||||
///Constructor
|
||||
@ -104,7 +100,7 @@ VideoRenderer::~VideoRenderer()
|
||||
}
|
||||
|
||||
///Get the data from shared memory and transform it into a QByteArray
|
||||
QByteArray VideoRenderer::renderToBitmap(bool& ok)
|
||||
QByteArray VideoRenderer::renderToBitmap(QByteArray& data,bool& ok)
|
||||
{
|
||||
if (!shmLock()) {
|
||||
ok = false;
|
||||
@ -133,7 +129,14 @@ QByteArray VideoRenderer::renderToBitmap(bool& ok)
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray data(m_pShmArea->data,m_pShmArea->m_BufferSize);
|
||||
if (data.size() != m_pShmArea->m_BufferSize)
|
||||
data.resize(m_pShmArea->m_BufferSize);
|
||||
//data = m_pShmArea->m_Data;
|
||||
memcpy(data.data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
|
||||
QByteArray data2(m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
|
||||
// QByteArray data3(m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
|
||||
// QByteArray data4(m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
|
||||
// QByteArray data5(m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
|
||||
m_BufferGen = m_pShmArea->m_BufferGen;
|
||||
shmUnlock();
|
||||
return data;
|
||||
@ -294,12 +297,14 @@ void VideoModel::deviceEvent()
|
||||
void VideoModel::timedEvents()
|
||||
{
|
||||
bool ok = true;
|
||||
m_Frame = m_pRenderer->renderToBitmap(ok);
|
||||
qDebug() << "Render" << ok;
|
||||
if (ok)
|
||||
QByteArray ba;
|
||||
m_pRenderer->renderToBitmap(m_Frame,ok);
|
||||
if (ok == true)
|
||||
emit frameUpdated();
|
||||
else
|
||||
else {
|
||||
qDebug() << "Frame dropped";
|
||||
usleep(rand()%100000); //Be sure it can come back in sync
|
||||
}
|
||||
}
|
||||
|
||||
///Return the current framerate
|
||||
@ -337,4 +342,9 @@ void VideoModel::stoppedDecoding(QString id, QString shmPath)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(shmPath)
|
||||
}
|
||||
|
||||
char* VideoModel::rawData()
|
||||
{
|
||||
return m_pRenderer->m_pShmArea->m_Data;
|
||||
}
|
@ -29,6 +29,7 @@ class QTimer;
|
||||
//SFLPhone
|
||||
#include "VideoDevice.h"
|
||||
class VideoRenderer;
|
||||
struct SHMHeader;
|
||||
|
||||
///VideoModel: Video event dispatcher
|
||||
class LIB_EXPORT VideoModel : public QObject {
|
||||
@ -41,6 +42,8 @@ public:
|
||||
bool isPreviewing ();
|
||||
QByteArray getCurrentFrame ();
|
||||
Resolution getActiveResolution();
|
||||
char* rawData ();
|
||||
|
||||
|
||||
//Setters
|
||||
void setBufferSize(uint size);
|
||||
@ -70,8 +73,6 @@ public slots:
|
||||
void startPreview();
|
||||
|
||||
private slots:
|
||||
//void receivingEvent(int shmKey, int semKey, int videoBufferSize, int destWidth, int destHeight);
|
||||
//void stoppedReceivingEvent(int shmKey, int semKey);
|
||||
void startedDecoding(QString id, QString shmPath, int width, int height);
|
||||
void stoppedDecoding(QString id, QString shmPath);
|
||||
void deviceEvent();
|
||||
|
528
kde/src/widgets/AcceleratedVideoWidget.cpp
Normal file
528
kde/src/widgets/AcceleratedVideoWidget.cpp
Normal file
@ -0,0 +1,528 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2012 by Savoir-Faire Linux *
|
||||
* Author : Emmanuel Lepage Valle <emmanuel.lepage@savoirfairelinux.com >*
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
**************************************************************************/
|
||||
#include "AcceleratedVideoWidget.h"
|
||||
#include <QPixmap>
|
||||
#include <KDebug>
|
||||
#include "../lib/VideoModel.h"
|
||||
|
||||
|
||||
|
||||
#include <QtGui/QImage>
|
||||
#include <QtCore/QPropertyAnimation>
|
||||
|
||||
static const qreal FACE_SIZE = 0.4;
|
||||
|
||||
static const qreal speeds[] = { 1.8f, 2.4f, 3.6f };
|
||||
static const qreal amplitudes[] = { 2.0f, 2.5f, 3.0f };
|
||||
|
||||
static inline void qSetColor(float colorVec[], QColor c)
|
||||
{
|
||||
colorVec[0] = c.redF();
|
||||
colorVec[1] = c.greenF();
|
||||
colorVec[2] = c.blueF();
|
||||
colorVec[3] = c.alphaF();
|
||||
}
|
||||
|
||||
int Geometry::append(const QVector3D &a, const QVector3D &n, const QVector2D &t)
|
||||
{
|
||||
int v = vertices.count();
|
||||
vertices.append(a);
|
||||
normals.append(n);
|
||||
texCoords.append(t);
|
||||
faces.append(v);
|
||||
colors.append(QVector4D(0.6f, 0.6f, 0.6f, 1.0f));
|
||||
return v;
|
||||
}
|
||||
|
||||
void Geometry::addQuad(const QVector3D &a, const QVector3D &b,
|
||||
const QVector3D &c, const QVector3D &d,
|
||||
const QVector<QVector2D> &tex)
|
||||
{
|
||||
QVector3D norm = QVector3D::normal(a, b, c);
|
||||
// append first triangle
|
||||
int aref = append(a, norm, tex[0]);
|
||||
append(b, norm, tex[1]);
|
||||
int cref = append(c, norm, tex[2]);
|
||||
// append second triangle
|
||||
faces.append(aref);
|
||||
faces.append(cref);
|
||||
append(d, norm, tex[3]);
|
||||
}
|
||||
|
||||
void Geometry::loadArrays() const
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
|
||||
glNormalPointer(GL_FLOAT, 0, normals.constData());
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());
|
||||
glColorPointer(4, GL_FLOAT, 0, colors.constData());
|
||||
}
|
||||
|
||||
void Geometry::setColors(int start, GLfloat colorArray[4][4])
|
||||
{
|
||||
int off = faces[start];
|
||||
for (int i = 0; i < 4; ++i)
|
||||
colors[i + off] = QVector4D(colorArray[i][0],
|
||||
colorArray[i][1],
|
||||
colorArray[i][2],
|
||||
colorArray[i][3]);
|
||||
}
|
||||
|
||||
Tile::Tile(const QVector3D &loc)
|
||||
: location(loc)
|
||||
, start(0)
|
||||
, count(0)
|
||||
, useFlatColor(false)
|
||||
, geom(0)
|
||||
{
|
||||
qSetColor(faceColor, QColor(Qt::darkGray));
|
||||
}
|
||||
|
||||
void Tile::setColors(GLfloat colorArray[4][4])
|
||||
{
|
||||
useFlatColor = true;
|
||||
geom->setColors(start, colorArray);
|
||||
}
|
||||
|
||||
static inline void qMultMatrix(const QMatrix4x4 &mat)
|
||||
{
|
||||
if (sizeof(qreal) == sizeof(GLfloat))
|
||||
glMultMatrixf((GLfloat*)mat.constData());
|
||||
#ifndef QT_OPENGL_ES
|
||||
else if (sizeof(qreal) == sizeof(GLdouble))
|
||||
glMultMatrixd((GLdouble*)mat.constData());
|
||||
#endif
|
||||
else
|
||||
{
|
||||
GLfloat fmat[16];
|
||||
qreal const *r = mat.constData();
|
||||
for (int i = 0; i < 16; ++i)
|
||||
fmat[i] = r[i];
|
||||
glMultMatrixf(fmat);
|
||||
}
|
||||
}
|
||||
|
||||
void Tile::draw() const
|
||||
{
|
||||
QMatrix4x4 mat;
|
||||
mat.translate(location);
|
||||
mat.rotate(orientation);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
qMultMatrix(mat);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, faceColor);
|
||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, geom->indices() + start);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
TileBuilder::TileBuilder(Geometry *g, qreal depth, qreal size)
|
||||
: verts(4)
|
||||
, tex(4)
|
||||
, start(g->count())
|
||||
, count(0)
|
||||
, geom(g)
|
||||
{
|
||||
// front face - make a square with bottom-left at origin
|
||||
verts[br].setX(size);
|
||||
verts[tr].setX(size);
|
||||
verts[tr].setY(size);
|
||||
verts[tl].setY(size);
|
||||
|
||||
// these vert numbers are good for the tex-coords
|
||||
for (int i = 0; i < 4; ++i)
|
||||
tex[i] = verts[i].toVector2D();
|
||||
|
||||
// now move verts half cube width across so cube is centered on origin
|
||||
for (int i = 0; i < 4; ++i)
|
||||
verts[i] -= QVector3D(size / 2.0f, size / 2.0f, -depth);
|
||||
|
||||
// add the front face
|
||||
g->addQuad(verts[bl], verts[br], verts[tr], verts[tl], tex);
|
||||
|
||||
count = g->count() - start;
|
||||
}
|
||||
|
||||
void TileBuilder::initialize(Tile *tile) const
|
||||
{
|
||||
tile->start = start;
|
||||
tile->count = count;
|
||||
tile->geom = geom;
|
||||
qSetColor(tile->faceColor, color);
|
||||
}
|
||||
|
||||
Tile *TileBuilder::newTile(const QVector3D &loc) const
|
||||
{
|
||||
Tile *tile = new Tile(loc);
|
||||
initialize(tile);
|
||||
return tile;
|
||||
}
|
||||
|
||||
Cube::Cube(const QVector3D &loc)
|
||||
: Tile(loc)
|
||||
, rot(0.0f)
|
||||
, r(0), a(0)
|
||||
{
|
||||
}
|
||||
|
||||
Cube::~Cube()
|
||||
{
|
||||
}
|
||||
|
||||
void Cube::setAltitude(qreal a)
|
||||
{
|
||||
if (location.y() != a)
|
||||
{
|
||||
location.setY(a);
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Cube::setRange(qreal r)
|
||||
{
|
||||
if (location.x() != r)
|
||||
{
|
||||
location.setX(r);
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Cube::setRotation(qreal r)
|
||||
{
|
||||
if (r != rot)
|
||||
{
|
||||
orientation = QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 1.0f, 1.0f), r);
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Cube::removeBounce()
|
||||
{
|
||||
delete a;
|
||||
a = 0;
|
||||
delete r;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
void Cube::startAnimation()
|
||||
{
|
||||
if (r)
|
||||
{
|
||||
r->start();
|
||||
r->setCurrentTime(startx);
|
||||
}
|
||||
if (a)
|
||||
a->start();
|
||||
if (rtn)
|
||||
rtn->start();
|
||||
}
|
||||
|
||||
void Cube::setAnimationPaused(bool paused)
|
||||
{
|
||||
if (paused)
|
||||
{
|
||||
if (r)
|
||||
r->pause();
|
||||
if (a)
|
||||
a->pause();
|
||||
if (rtn)
|
||||
rtn->pause();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r)
|
||||
r->resume();
|
||||
if (a)
|
||||
a->resume();
|
||||
if (rtn)
|
||||
rtn->resume();
|
||||
}
|
||||
}
|
||||
|
||||
CubeBuilder::CubeBuilder(Geometry *g, qreal depth, qreal size)
|
||||
: TileBuilder(g, depth)
|
||||
, ix(0)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
verts[i].setZ(size / 2.0f);
|
||||
// back face - "extrude" verts down
|
||||
QVector<QVector3D> back(verts);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
back[i].setZ(-size / 2.0f);
|
||||
|
||||
// add the back face
|
||||
g->addQuad(back[br], back[bl], back[tl], back[tr], tex);
|
||||
|
||||
// add the sides
|
||||
g->addQuad(back[bl], back[br], verts[br], verts[bl], tex);
|
||||
g->addQuad(back[br], back[tr], verts[tr], verts[br], tex);
|
||||
g->addQuad(back[tr], back[tl], verts[tl], verts[tr], tex);
|
||||
g->addQuad(back[tl], back[bl], verts[bl], verts[tl], tex);
|
||||
|
||||
count = g->count() - start;
|
||||
}
|
||||
|
||||
Cube *CubeBuilder::newCube(const QVector3D &loc) const
|
||||
{
|
||||
Cube *c = new Cube(loc);
|
||||
initialize(c);
|
||||
qreal d = 4000.0f;
|
||||
qreal d3 = d / 3.0f;
|
||||
// Animate movement from left to right
|
||||
c->r = new QPropertyAnimation(c, "range");
|
||||
c->r->setStartValue(-1.3f);
|
||||
c->r->setEndValue(1.3f);
|
||||
c->startx = ix * d3 * 3.0f;
|
||||
c->r->setDuration(d * 4.0f);
|
||||
c->r->setLoopCount(-1);
|
||||
c->r->setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
|
||||
// Animate movement from bottom to top
|
||||
c->a = new QPropertyAnimation(c, "altitude");
|
||||
c->a->setEndValue(loc.y());
|
||||
c->a->setStartValue(loc.y() + amplitudes[ix]);
|
||||
c->a->setDuration(d / speeds[ix]);
|
||||
c->a->setLoopCount(-1);
|
||||
c->a->setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
|
||||
// Animate rotation
|
||||
c->rtn = new QPropertyAnimation(c, "rotation");
|
||||
c->rtn->setStartValue(c->rot);
|
||||
c->rtn->setEndValue(359.0f);
|
||||
c->rtn->setDuration(d * 2.0f);
|
||||
c->rtn->setLoopCount(-1);
|
||||
c->rtn->setDuration(d / 2);
|
||||
ix = (ix + 1) % 3;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
void AcceleratedVideoWidget::newFrameEvent()
|
||||
{
|
||||
qDebug() << "New frame event";
|
||||
QSize size(VideoModel::getInstance()->getActiveResolution().width, VideoModel::getInstance()->getActiveResolution().height);
|
||||
m_Image = QImage((uchar*)VideoModel::getInstance()->rawData() , size.width(), size.height(), QImage::Format_ARGB32 );
|
||||
paintGL();
|
||||
}
|
||||
|
||||
static GLfloat colorArray[][4] = {
|
||||
{0.243f , 0.423f , 0.125f , 1.0f},
|
||||
{0.176f , 0.31f , 0.09f , 1.0f},
|
||||
{0.4f , 0.69f , 0.212f , 1.0f},
|
||||
{0.317f , 0.553f , 0.161f , 1.0f}
|
||||
};
|
||||
|
||||
AcceleratedVideoWidget::AcceleratedVideoWidget(QWidget *parent)
|
||||
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
|
||||
, geom(0)
|
||||
, cube(0)
|
||||
{
|
||||
// create the pbuffer
|
||||
QGLFormat pbufferFormat = format();
|
||||
pbufferFormat.setSampleBuffers(false);
|
||||
pbuffer = new QGLPixelBuffer(QSize(512, 512), pbufferFormat, this);
|
||||
setWindowTitle(tr("OpenGL pbuffers"));
|
||||
initializeGeometry();
|
||||
connect(VideoModel::getInstance(),SIGNAL(frameUpdated()),this,SLOT(newFrameEvent()));
|
||||
}
|
||||
|
||||
AcceleratedVideoWidget::~AcceleratedVideoWidget()
|
||||
{
|
||||
pbuffer->releaseFromDynamicTexture();
|
||||
glDeleteTextures(1, &dynamicTexture);
|
||||
delete pbuffer;
|
||||
|
||||
qDeleteAll(cubes);
|
||||
qDeleteAll(tiles);
|
||||
delete cube;
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::initializeGL()
|
||||
{
|
||||
initCommon();
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
|
||||
initPbuffer();
|
||||
cube->startAnimation();
|
||||
connect(cube, SIGNAL(changed()), this, SLOT(update()));
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
cubes[i]->startAnimation();
|
||||
connect(cubes[i], SIGNAL(changed()), this, SLOT(update()));
|
||||
}
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::paintGL()
|
||||
{
|
||||
QSize size(VideoModel::getInstance()->getActiveResolution().width, VideoModel::getInstance()->getActiveResolution().height);
|
||||
if (size != minimumSize())
|
||||
setMinimumSize(size);
|
||||
|
||||
pbuffer->makeCurrent();
|
||||
drawPbuffer();
|
||||
// On direct render platforms, drawing onto the pbuffer context above
|
||||
// automatically updates the dynamic texture. For cases where rendering
|
||||
// directly to a texture is not supported, explicitly copy.
|
||||
if (!hasDynamicTextureUpdate)
|
||||
pbuffer->updateDynamicTexture(dynamicTexture);
|
||||
makeCurrent();
|
||||
|
||||
// Use the pbuffer as a texture to render the scene
|
||||
glBindTexture(GL_TEXTURE_2D, dynamicTexture);
|
||||
|
||||
// set up to render the scene
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0f, 0.0f, -10.0f);
|
||||
|
||||
// draw the background
|
||||
glPushMatrix();
|
||||
glScalef(aspect, 1.0f, 1.0f);
|
||||
for (int i = 0; i < tiles.count(); ++i)
|
||||
tiles[i]->draw();
|
||||
glPopMatrix();
|
||||
|
||||
// draw the bouncing cubes
|
||||
for (int i = 0; i < cubes.count(); ++i)
|
||||
cubes[i]->draw();
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::initializeGeometry()
|
||||
{
|
||||
geom = new Geometry();
|
||||
CubeBuilder cBuilder(geom, 0.5);
|
||||
cBuilder.setColor(QColor(255, 255, 255, 212));
|
||||
// build the 3 bouncing, spinning cubes
|
||||
for (int i = 0; i < 3; ++i)
|
||||
cubes.append(cBuilder.newCube(QVector3D((float)(i-1), -1.5f, 5 - i)));
|
||||
|
||||
// build the spinning cube which goes in the dynamic texture
|
||||
cube = cBuilder.newCube();
|
||||
cube->removeBounce();
|
||||
|
||||
// build the background tiles
|
||||
TileBuilder tBuilder(geom);
|
||||
tBuilder.setColor(QColor(Qt::white));
|
||||
for (int c = -2; c <= +2; ++c)
|
||||
for (int r = -2; r <= +2; ++r)
|
||||
tiles.append(tBuilder.newTile(QVector3D(c, r, 0)));
|
||||
|
||||
// graded backdrop for the pbuffer scene
|
||||
TileBuilder bBuilder(geom, 0.0f, 2.0f);
|
||||
bBuilder.setColor(QColor(102, 176, 54, 210));
|
||||
backdrop = bBuilder.newTile(QVector3D(0.0f, 0.0f, -1.5f));
|
||||
backdrop->setColors(colorArray);
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::initCommon()
|
||||
{
|
||||
qglClearColor(QColor(Qt::darkGray));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
geom->loadArrays();
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::perspectiveProjection()
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef QT_OPENGL_ES
|
||||
glFrustumf(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
|
||||
#else
|
||||
glFrustum(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0);
|
||||
#endif
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::orthographicProjection()
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef QT_OPENGL_ES
|
||||
glOrthof(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
|
||||
#else
|
||||
glOrtho(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0);
|
||||
#endif
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::resizeGL(int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
aspect = (qreal)width / (qreal)(height ? height : 1);
|
||||
perspectiveProjection();
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::drawPbuffer()
|
||||
{
|
||||
cubeTexture = bindTexture(m_Image);
|
||||
//initPbuffer();
|
||||
|
||||
orthographicProjection();
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
backdrop->draw();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, cubeTexture);
|
||||
glDisable(GL_CULL_FACE);
|
||||
cube->draw();
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::initPbuffer()
|
||||
{
|
||||
pbuffer->makeCurrent();
|
||||
|
||||
// cubeTexture = bindTexture(QImage("/home/lepagee/ccu_12.png"));
|
||||
cubeTexture = bindTexture(m_Image);
|
||||
|
||||
initCommon();
|
||||
|
||||
// generate a texture that has the same size/format as the pbuffer
|
||||
dynamicTexture = pbuffer->generateDynamicTexture();
|
||||
|
||||
// bind the dynamic texture to the pbuffer - this is a no-op under X11
|
||||
hasDynamicTextureUpdate = pbuffer->bindToDynamicTexture(dynamicTexture);
|
||||
makeCurrent();
|
||||
}
|
||||
|
||||
void AcceleratedVideoWidget::setAnimationPaused(bool enable)
|
||||
{
|
||||
cube->setAnimationPaused(enable);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
cubes[i]->setAnimationPaused(enable);
|
||||
}
|
181
kde/src/widgets/AcceleratedVideoWidget.h
Normal file
181
kde/src/widgets/AcceleratedVideoWidget.h
Normal file
@ -0,0 +1,181 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009-2012 by Savoir-Faire Linux *
|
||||
* Author : Emmanuel Lepage Valle <emmanuel.lepage@savoirfairelinux.com >*
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
**************************************************************************/
|
||||
#ifndef ACCELERATEDVIDEOWIDGET_H
|
||||
#define ACCELERATEDVIDEOWIDGET_H
|
||||
#include <QGLPixelBuffer>
|
||||
#include <QGLWidget>
|
||||
#include <QPixmap>
|
||||
|
||||
#include <QtOpenGL/qgl.h>
|
||||
#include <QtCore/qvector.h>
|
||||
#include <QtGui/qmatrix4x4.h>
|
||||
#include <QtGui/qvector3d.h>
|
||||
#include <QtGui/qvector2d.h>
|
||||
|
||||
|
||||
class Geometry;
|
||||
//class Cube;
|
||||
class Tile;
|
||||
|
||||
|
||||
|
||||
class QPropertyAnimation;
|
||||
|
||||
class Geometry
|
||||
{
|
||||
public:
|
||||
void loadArrays() const;
|
||||
void addQuad(const QVector3D &a, const QVector3D &b,
|
||||
const QVector3D &c, const QVector3D &d,
|
||||
const QVector<QVector2D> &tex);
|
||||
void setColors(int start, GLfloat colors[4][4]);
|
||||
const GLushort *indices() const { return faces.constData(); }
|
||||
int count() const { return faces.count(); }
|
||||
private:
|
||||
QVector<GLushort> faces;
|
||||
QVector<QVector3D> vertices;
|
||||
QVector<QVector3D> normals;
|
||||
QVector<QVector2D> texCoords;
|
||||
QVector<QVector4D> colors;
|
||||
int append(const QVector3D &a, const QVector3D &n, const QVector2D &t);
|
||||
void addTri(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &n);
|
||||
friend class Tile;
|
||||
};
|
||||
|
||||
class Tile
|
||||
{
|
||||
public:
|
||||
void draw() const;
|
||||
void setColors(GLfloat[4][4]);
|
||||
protected:
|
||||
Tile(const QVector3D &loc = QVector3D());
|
||||
QVector3D location;
|
||||
QQuaternion orientation;
|
||||
private:
|
||||
int start;
|
||||
int count;
|
||||
bool useFlatColor;
|
||||
GLfloat faceColor[4];
|
||||
Geometry *geom;
|
||||
friend class TileBuilder;
|
||||
};
|
||||
|
||||
class TileBuilder
|
||||
{
|
||||
public:
|
||||
enum { bl, br, tr, tl };
|
||||
TileBuilder(Geometry *, qreal depth = 0.0f, qreal size = 1.0f);
|
||||
Tile *newTile(const QVector3D &loc = QVector3D()) const;
|
||||
void setColor(QColor c) { color = c; }
|
||||
protected:
|
||||
void initialize(Tile *) const;
|
||||
QVector<QVector3D> verts;
|
||||
QVector<QVector2D> tex;
|
||||
int start;
|
||||
int count;
|
||||
Geometry *geom;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
class Cube : public QObject, public Tile
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal range READ range WRITE setRange)
|
||||
Q_PROPERTY(qreal altitude READ altitude WRITE setAltitude)
|
||||
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
|
||||
public:
|
||||
Cube(const QVector3D &loc = QVector3D());
|
||||
~Cube();
|
||||
qreal range() { return location.x(); }
|
||||
void setRange(qreal r);
|
||||
qreal altitude() { return location.y(); }
|
||||
void setAltitude(qreal a);
|
||||
qreal rotation() { return rot; }
|
||||
void setRotation(qreal r);
|
||||
void removeBounce();
|
||||
void startAnimation();
|
||||
void setAnimationPaused(bool paused);
|
||||
signals:
|
||||
void changed();
|
||||
private:
|
||||
qreal rot;
|
||||
QPropertyAnimation *r;
|
||||
QPropertyAnimation *a;
|
||||
QPropertyAnimation *rtn;
|
||||
qreal startx;
|
||||
friend class CubeBuilder;
|
||||
};
|
||||
|
||||
class CubeBuilder : public TileBuilder
|
||||
{
|
||||
public:
|
||||
CubeBuilder(Geometry *, qreal depth = 0.0f, qreal size = 1.0f);
|
||||
Cube *newCube(const QVector3D &loc = QVector3D()) const;
|
||||
private:
|
||||
mutable int ix;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///Hardware accelerated version of VideoWidget
|
||||
class AcceleratedVideoWidget : public QGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AcceleratedVideoWidget(QWidget* parent);
|
||||
~AcceleratedVideoWidget();
|
||||
|
||||
private:
|
||||
QGLPixelBuffer* m_pPixBuf;
|
||||
QImage m_Image;
|
||||
|
||||
qreal aspect;
|
||||
GLuint dynamicTexture;
|
||||
GLuint cubeTexture;
|
||||
bool hasDynamicTextureUpdate;
|
||||
QGLPixelBuffer *pbuffer;
|
||||
Geometry *geom;
|
||||
Cube *cube;
|
||||
Tile *backdrop;
|
||||
QList<Cube *> cubes;
|
||||
QList<Tile *> tiles;
|
||||
|
||||
void initializeGeometry();
|
||||
void initPbuffer();
|
||||
void initCommon();
|
||||
void perspectiveProjection();
|
||||
void orthographicProjection();
|
||||
void drawPbuffer();
|
||||
void setAnimationPaused(bool enable);
|
||||
|
||||
protected:
|
||||
void initializeGL();
|
||||
void resizeGL(int w, int h);
|
||||
void paintGL();
|
||||
void mousePressEvent(QMouseEvent *) { setAnimationPaused(true); }
|
||||
void mouseReleaseEvent(QMouseEvent *) { setAnimationPaused(false); }
|
||||
|
||||
private slots:
|
||||
void newFrameEvent();
|
||||
};
|
||||
#endif
|
@ -41,13 +41,11 @@ void VideoWidget::paintEvent(QPaintEvent* event)
|
||||
|
||||
void VideoWidget::repaint2()
|
||||
{
|
||||
kDebug() << "Repainting";
|
||||
QSize size(VideoModel::getInstance()->getActiveResolution().width, VideoModel::getInstance()->getActiveResolution().height);
|
||||
if (size != minimumSize())
|
||||
setMinimumSize(size);
|
||||
//if (m_Image)
|
||||
// delete m_Image;
|
||||
m_Image = new QImage(size,QImage::Format_ARGB32);
|
||||
m_Image->loadFromData(VideoModel::getInstance()->getCurrentFrame(),"BMP");
|
||||
if (m_Image)
|
||||
delete m_Image;
|
||||
m_Image = new QImage((uchar*)VideoModel::getInstance()->rawData() , size.width(), size.height(), QImage::Format_ARGB32 );
|
||||
repaint();
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
@ -226,6 +226,11 @@ order to use an ANSI C compiler:
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
|
Reference in New Issue
Block a user