[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [sflphone-kde/contact_refactor] src: [ #44095 ] Implement a video flip-buffer, use double buffer ins
From: Emmanuel Lepage Vallee <emmanuel.lepage () savoirfairelinux ! com>
Date: 2014-03-31 16:58:29
Message-ID: E1WUfXZ-0000Ha-1i () scm ! kde ! org
[Download RAW message or body]
Git commit 331f6777b218c7bfd50014acb9be4eb50306d60b by Emmanuel Lepage Vallee.
Committed on 31/03/2014 at 16:58.
Pushed by lepagevalleeemmanuel into branch 'contact_refactor'.
[ #44095 ] Implement a video flip-buffer, use double buffer instead of triple ones
M +2 -1 src/klib/minimalhistorybackend.cpp
M +14 -5 src/lib/videomodel.cpp
M +4 -1 src/lib/videomodel.h
M +33 -16 src/lib/videorenderer.cpp
M +4 -2 src/lib/videorenderer.h
M +3 -12 src/widgets/videoglframe.cpp
http://commits.kde.org/sflphone-kde/331f6777b218c7bfd50014acb9be4eb50306d60b
diff --git a/src/klib/minimalhistorybackend.cpp b/src/klib/minimalhistorybackend.cpp
index 0a84429..e4424c3 100644
--- a/src/klib/minimalhistorybackend.cpp
+++ b/src/klib/minimalhistorybackend.cpp
@@ -107,10 +107,11 @@ bool MinimalHistoryBackend::append(const Call* call)
const QString direction = (call->direction()==Call::Direction::INCOMING)?
Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING;
QTextStream streamFileOut(&file);
+ const Account* a = call->account();
streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID \
).arg(call->id() );
streamFileOut << \
QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START \
).arg(call->startTimeStamp() );
streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP \
).arg(call->stopTimeStamp() );
- streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID \
).arg(call->account()->id() ); + streamFileOut << \
QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID ).arg(a?a->id():"" \
);
streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME \
).arg(call->peerName() );
streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER \
).arg(call->peerPhoneNumber()->uri() );
streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION \
).arg(direction );
diff --git a/src/lib/videomodel.cpp b/src/lib/videomodel.cpp
index b800837..90d64c0 100644
--- a/src/lib/videomodel.cpp
+++ b/src/lib/videomodel.cpp
@@ -17,6 +17,9 @@
***************************************************************************/
#include "videomodel.h"
+//Qt
+#include <QtCore/QMutex>
+
//SFLPhone
#include "dbus/videomanager.h"
#include "videodevice.h"
@@ -28,7 +31,7 @@
VideoModel* VideoModel::m_spInstance = nullptr;
///Constructor
-VideoModel::VideoModel():QThread(),m_BufferSize(0),m_ShmKey(0),m_SemKey(0),m_PreviewState(false)
+VideoModel::VideoModel():QThread(),m_BufferSize(0),m_ShmKey(0),m_SemKey(0),m_PreviewState(false),m_SSMutex(new \
QMutex()) {
VideoInterface& interface = DBus::VideoManager::instance();
connect( &interface , SIGNAL(deviceEvent()) , this, \
SLOT(deviceEvent()) ); @@ -164,10 +167,10 @@ void \
VideoModel::stoppedDecoding(const QString& id, const QString& shmPath) delete r;
}
-void VideoModel::run()
-{
- exec();
-}
+// void VideoModel::run()
+// {
+// exec();
+// }
void VideoModel::setActiveDevice(const VideoDevice* device)
@@ -224,3 +227,9 @@ VideoDevice* VideoModel::device(const QString &id)
{
return m_hDevices[id];
}
+
+QMutex* VideoModel::startStopMutex() const
+{
+ return m_SSMutex;
+}
+
diff --git a/src/lib/videomodel.h b/src/lib/videomodel.h
index b23006c..6117df9 100644
--- a/src/lib/videomodel.h
+++ b/src/lib/videomodel.h
@@ -28,6 +28,7 @@
#include "videodevice.h"
class VideoRenderer;
class Call;
+class QMutex;
struct SHMHeader;
///VideoModel: Video event dispatcher
@@ -47,6 +48,7 @@ public:
QList<VideoDevice*> devices();
VideoDevice* activeDevice() const;
VideoDevice* device(const QString &id);
+ QMutex* startStopMutex() const;
//Setters
void setBufferSize(uint size);
@@ -54,7 +56,7 @@ public:
void switchDevice(const VideoDevice* device) const;
protected:
- void run();
+// void run();
private:
//Constructor
@@ -69,6 +71,7 @@ private:
uint m_BufferSize ;
uint m_ShmKey ;
uint m_SemKey ;
+ QMutex* m_SSMutex ;
QHash<QString,VideoRenderer*> m_lRenderers;
QHash<QString,VideoDevice*> m_hDevices ;
diff --git a/src/lib/videorenderer.cpp b/src/lib/videorenderer.cpp
index d221e69..89cd560 100644
--- a/src/lib/videorenderer.cpp
+++ b/src/lib/videorenderer.cpp
@@ -19,6 +19,7 @@
#include <QtCore/QDebug>
#include <QtCore/QMutex>
+#include <QtCore/QThread>
#include <sys/ipc.h>
#include <sys/sem.h>
@@ -36,6 +37,7 @@
#endif
#include <QtCore/QTimer>
+#include "videomodel.h"
///Shared memory object
struct SHMHeader{
@@ -58,7 +60,7 @@ VideoRenderer::VideoRenderer(const QString& id, const QString& \
shmPath, Resoluti m_Width(res.width()), m_Height(res.height()), m_ShmPath(shmPath), \
fd(-1), m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0),
m_isRendering(false),m_pTimer(nullptr),m_Res(res),m_pMutex(new QMutex()),
- m_Id(id)
+ m_Id(id),m_FrameIdx(false),m_pSSMutex(new QMutex())
{
setObjectName("VideoRenderer:"+id);
}
@@ -71,7 +73,7 @@ VideoRenderer::~VideoRenderer()
}
///Get the data from shared memory and transform it into a QByteArray
-bool VideoRenderer::renderToBitmap(QByteArray& data)
+bool VideoRenderer::renderToBitmap()
{
#ifdef Q_OS_LINUX
if (!m_isRendering) {
@@ -86,7 +88,10 @@ bool VideoRenderer::renderToBitmap(QByteArray& data)
while (m_BufferGen == m_pShmArea->m_BufferGen) {
shmUnlock();
const struct timespec timeout = createTimeout();
+ if(!VideoModel::instance()->startStopMutex()->tryLock())
+ return false;
int err = sem_timedwait(&m_pShmArea->notification, &timeout);
+ VideoModel::instance()->startStopMutex()->unlock();
// Useful for debugging
// switch (errno ) {
// case EINTR:
@@ -124,15 +129,17 @@ bool VideoRenderer::renderToBitmap(QByteArray& data)
return false;
}
- if (data.size() != m_pShmArea->m_BufferSize)
- data.resize(m_pShmArea->m_BufferSize);
- memcpy(data.data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
+ bool otherFrame = ! m_FrameIdx;
+ if (m_Frame[otherFrame].size() != m_pShmArea->m_BufferSize)
+ m_Frame[otherFrame].resize(m_pShmArea->m_BufferSize);
+ memcpy(m_Frame[otherFrame].data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
m_BufferGen = m_pShmArea->m_BufferGen;
shmUnlock();
+ m_FrameIdx = !m_FrameIdx;
// return data;
+// m_pSSMutex->unlock();
return true;
#else
- Q_UNUSED(data)
return false;
#endif
}
@@ -254,10 +261,9 @@ timespec VideoRenderer::createTimeout()
///Update the buffer
void VideoRenderer::timedEvents()
{
- m_pMutex->lock();
- bool ok = renderToBitmap(m_Frame);
- m_pMutex->unlock();
+ bool ok = renderToBitmap();
+
if (ok == true) {
emit frameUpdated();
}
@@ -270,20 +276,32 @@ void VideoRenderer::timedEvents()
///Start the rendering loop
void VideoRenderer::startRendering()
{
+ VideoModel::instance()->startStopMutex()->lock();
QMutexLocker locker(m_pMutex);
startShm();
if (!m_pTimer) {
- m_pTimer = new QTimer(this);
+ m_pTimer = new QTimer(nullptr);
+
+// m_pTimer->moveToThread(thread());
connect(m_pTimer,SIGNAL(timeout()),this,SLOT(timedEvents()));
- m_pTimer->setInterval(42);
+ m_pTimer->setInterval(30);
}
- m_pTimer->start();
+
+ if (!m_pTimer->isActive()) {
+ qDebug() << "Is running" << thread()->isRunning();
+ m_pTimer->start();
+ }
+ else
+ qDebug() << "Timer already started!";
+
m_isRendering = true;
+ VideoModel::instance()->startStopMutex()->unlock();
}
///Stop the rendering loop
void VideoRenderer::stopRendering()
{
+ VideoModel::instance()->startStopMutex()->lock();
QMutexLocker locker(m_pMutex);
m_isRendering = false;
qDebug() << "Stopping rendering on" << m_Id;
@@ -291,8 +309,7 @@ void VideoRenderer::stopRendering()
m_pTimer->stop();
emit stopped();
stopShm();
- //qDebug() << "Video stopped for call" << id;
- //emit videoStopped();
+ VideoModel::instance()->startStopMutex()->unlock();
}
@@ -305,7 +322,7 @@ void VideoRenderer::stopRendering()
///Get the raw bytes directly from the SHM, not recommended, but optimal
const char* VideoRenderer::rawData()
{
- return m_isRendering?m_Frame.data():nullptr;
+ return m_isRendering?m_Frame[m_FrameIdx].data():nullptr;
}
///Is this redenrer active
@@ -317,7 +334,7 @@ bool VideoRenderer::isRendering()
///Return the current framerate
QByteArray VideoRenderer::currentFrame()
{
- return m_Frame;
+ return m_Frame[m_FrameIdx];
}
///Return the current resolution
diff --git a/src/lib/videorenderer.h b/src/lib/videorenderer.h
index f18db3b..d07607a 100644
--- a/src/lib/videorenderer.h
+++ b/src/lib/videorenderer.h
@@ -70,9 +70,11 @@ class LIB_EXPORT VideoRenderer : public QObject {
uint m_BufferGen ;
bool m_isRendering;
QTimer* m_pTimer ;
- QByteArray m_Frame ;
+ QByteArray m_Frame[2] ;
+ bool m_FrameIdx ;
Resolution m_Res ;
QMutex* m_pMutex ;
+ QMutex* m_pSSMutex ;
QString m_Id ;
//Constants
@@ -82,7 +84,7 @@ class LIB_EXPORT VideoRenderer : public QObject {
timespec createTimeout();
bool shmLock ();
void shmUnlock ();
- bool renderToBitmap(QByteArray& data);
+ bool renderToBitmap();
private Q_SLOTS:
void timedEvents();
diff --git a/src/widgets/videoglframe.cpp b/src/widgets/videoglframe.cpp
index 0354718..3f32a25 100644
--- a/src/widgets/videoglframe.cpp
+++ b/src/widgets/videoglframe.cpp
@@ -106,10 +106,9 @@ void ThreadedPainter2::copyFrame()
if (m_pRenderer) {
m_pRenderer->mutex()->lock();
const QByteArray raw = m_pRenderer->currentFrame();
- if (m_Data)
- free(m_Data);
- m_Data = (char*)malloc(raw.size()*sizeof(char));
- memcpy(m_Data,raw.data(),raw.size());
+ if (!m_Data)
+ m_Data = (char*)malloc(raw.size()*sizeof(char));
+ m_Data = (char*)raw.data();
m_ActiveSize = m_pRenderer->activeResolution();
m_pRenderer->mutex()->unlock();
emit changed();
@@ -120,8 +119,6 @@ void ThreadedPainter2::draw(QPainter* p)
{
Q_UNUSED(p)
if (m_pRenderer && isRendering) {
-// QMutexLocker locker(&mutex);
-// m_pRenderer->mutex()->lock();
// save the GL state set for QPainter
saveGLState();
@@ -181,12 +178,6 @@ void ThreadedPainter2::draw(QPainter* p)
m_pPainter(new ThreadedPainter2(this,parent)),
m_pRenderer(nullptr)
{
-
-// Should work, does not
-// QThread* t = new QThread(this);
-// connect(t, SIGNAL(started()), m_pPainter, SLOT(rendererStarted()));
-// m_pPainter->moveToThread(t);
-// t->start();
connect(m_pPainter,SIGNAL(changed()),this,SLOT(slotEmitChanged()));
m_pPainter->tile_list = glGenLists(1);
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic