~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to kde/src/lib/videorenderer.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
 
 *   Copyright (C) 2012-2013 by Savoir-Faire Linux                          *
 
2
 *   Copyright (C) 2012-2014 by Savoir-Faire Linux                          *
3
3
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
4
4
 *                                                                          *
5
5
 *   This library is free software; you can redistribute it and/or          *
18
18
#include "videorenderer.h"
19
19
 
20
20
#include <QtCore/QDebug>
 
21
#include <QtCore/QMutex>
21
22
 
22
23
#include <sys/ipc.h>
23
24
#include <sys/sem.h>
37
38
#include <QtCore/QTimer>
38
39
 
39
40
///Shared memory object
40
 
struct SHMHeader {
41
 
    sem_t notification;
42
 
    sem_t mutex;
43
 
 
44
 
    unsigned m_BufferGen;
45
 
    int m_BufferSize;
46
 
 
47
 
    char m_Data[0];
 
41
struct SHMHeader{
 
42
   sem_t notification;
 
43
   sem_t mutex;
 
44
 
 
45
   unsigned m_BufferGen;
 
46
   int m_BufferSize;
 
47
   /* The header will be aligned on 16-byte boundaries */
 
48
   char padding[8];
 
49
 
 
50
#pragma GCC diagnostic push
 
51
#pragma GCC diagnostic ignored "-pedantic"
 
52
   char m_Data[];
 
53
#pragma GCC diagnostic pop
48
54
};
49
55
 
50
56
///Constructor
51
 
VideoRenderer::VideoRenderer(QString shmPath, Resolution res): QObject(0),
52
 
   m_Width(0), m_Height(0), m_ShmPath(QString()), fd(-1),
 
57
VideoRenderer::VideoRenderer(const QString& id, const QString& shmPath, Resolution res): QObject(nullptr),
 
58
   m_Width(res.width()), m_Height(res.height()), m_ShmPath(shmPath), fd(-1),
53
59
   m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0),
54
 
   m_isRendering(false),m_pTimer(nullptr),m_Res(res)
 
60
   m_isRendering(false),m_pTimer(nullptr),m_Res(res),m_pMutex(new QMutex()),
 
61
   m_Id(id)
55
62
{
56
 
   m_ShmPath = shmPath      ;
57
 
   m_Width   = res.width()  ;
58
 
   m_Height  = res.height() ;
 
63
   setObjectName("VideoRenderer:"+id);
59
64
}
60
65
 
61
66
///Destructor
66
71
}
67
72
 
68
73
///Get the data from shared memory and transform it into a QByteArray
69
 
QByteArray VideoRenderer::renderToBitmap(QByteArray& data,bool& ok)
 
74
bool VideoRenderer::renderToBitmap(QByteArray& data)
70
75
{
71
76
   if (!m_isRendering) {
72
 
      return QByteArray();
 
77
      return false;
73
78
   }
74
79
 
75
80
   if (!shmLock()) {
76
 
      ok = false;
77
 
      return QByteArray();
 
81
      return false;
78
82
   }
79
83
 
80
84
   // wait for a new buffer
106
110
//             break;
107
111
//       }
108
112
      if (err < 0) {
109
 
         ok = false;
110
 
         return QByteArray();
 
113
         return false;
111
114
      }
112
115
 
113
116
      if (!shmLock()) {
114
 
         ok = false;
115
 
         return QByteArray();
 
117
         return false;
116
118
      }
117
119
   }
118
120
 
119
121
   if (!resizeShm()) {
120
122
      qDebug() << "Could not resize shared memory";
121
 
      ok = false;
122
 
      return QByteArray();
 
123
      return false;
123
124
   }
124
125
 
125
126
   if (data.size() != m_pShmArea->m_BufferSize)
127
128
   memcpy(data.data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
128
129
   m_BufferGen = m_pShmArea->m_BufferGen;
129
130
   shmUnlock();
130
 
   return data;
 
131
//    return data;
 
132
   return true;
131
133
}
132
134
 
133
135
///Connect to the shared memory
140
142
 
141
143
   fd = shm_open(m_ShmPath.toAscii(), O_RDWR, 0);
142
144
   if (fd < 0) {
143
 
      qDebug() << "could not open shm area \"%s\", shm_open failed:%s" << m_ShmPath << strerror(errno);
 
145
      qDebug() << "could not open shm area " << m_ShmPath << ", shm_open failed:" << strerror(errno);
144
146
      return false;
145
147
   }
146
148
   m_ShmAreaLen = sizeof(SHMHeader);
 
149
   #pragma GCC diagnostic push
 
150
   #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
147
151
   m_pShmArea = (SHMHeader*) mmap(NULL, m_ShmAreaLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
152
   #pragma GCC diagnostic pop
148
153
   if (m_pShmArea == MAP_FAILED) {
149
154
      qDebug() << "Could not map shm area, mmap failed";
150
155
      return false;
151
156
   }
 
157
   emit started();
152
158
   return true;
153
159
}
154
160
 
173
179
 
174
180
      shmUnlock();
175
181
      if (munmap(m_pShmArea, m_ShmAreaLen)) {
176
 
            qDebug() << "Could not unmap shared area:%s" << strerror(errno);
 
182
            qDebug() << "Could not unmap shared area:" << strerror(errno);
177
183
            return false;
178
184
      }
179
185
 
 
186
      #pragma GCC diagnostic push
 
187
      #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
180
188
      m_pShmArea = (SHMHeader*) mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
189
      #pragma GCC diagnostic pop
181
190
      m_ShmAreaLen = new_size;
182
191
 
183
192
      if (!m_pShmArea) {
184
 
            m_pShmArea = 0;
 
193
            m_pShmArea = nullptr;
185
194
            qDebug() << "Could not remap shared area";
186
195
            return false;
187
196
      }
198
207
{
199
208
   const timespec timeout = createTimeout();
200
209
   /* We need an upper limit on how long we'll wait to avoid locking the whole GUI */
201
 
   if (sem_timedwait(&m_pShmArea->mutex, &timeout) == ETIMEDOUT) {
202
 
      qDebug() << "Timed out before shm lock was acquired";
 
210
   if (sem_timedwait(&m_pShmArea->mutex, &timeout) < 0) {
 
211
       if (errno == ETIMEDOUT)
 
212
           qDebug() << "Timed out before shm lock was acquired";
203
213
      return false;
204
214
   }
205
215
   return true;
231
241
///Update the buffer
232
242
void VideoRenderer::timedEvents()
233
243
{
234
 
   bool ok = true;
235
 
   QByteArray ba;
236
 
   renderToBitmap(m_Frame,ok);
 
244
   m_pMutex->lock();
 
245
 
 
246
   bool ok = renderToBitmap(m_Frame);
 
247
   m_pMutex->unlock();
237
248
   if (ok == true) {
238
249
      emit frameUpdated();
239
250
   }
246
257
///Start the rendering loop
247
258
void VideoRenderer::startRendering()
248
259
{
 
260
   QMutexLocker locker(m_pMutex);
249
261
   startShm();
250
262
   if (!m_pTimer) {
251
263
      m_pTimer = new QTimer(this);
259
271
///Stop the rendering loop
260
272
void VideoRenderer::stopRendering()
261
273
{
 
274
   QMutexLocker locker(m_pMutex);
262
275
   m_isRendering = false;
 
276
   qDebug() << "Stopping rendering on" << m_Id;
 
277
   if (m_pTimer)
 
278
      m_pTimer->stop();
 
279
   emit stopped();
263
280
   stopShm();
264
281
   //qDebug() << "Video stopped for call" << id;
265
282
   //emit videoStopped();
266
 
   if (m_pTimer)
267
 
      m_pTimer->stop();
268
283
}
269
284
 
270
285
 
277
292
///Get the raw bytes directly from the SHM, not recommended, but optimal
278
293
const char* VideoRenderer::rawData()
279
294
{
280
 
   return m_pShmArea->m_Data;
 
295
   return m_isRendering?m_Frame.data():nullptr;
281
296
}
282
297
 
283
298
///Is this redenrer active
287
302
}
288
303
 
289
304
///Return the current framerate
290
 
QByteArray VideoRenderer::getCurrentFrame()
 
305
QByteArray VideoRenderer::currentFrame()
291
306
{
292
307
   return m_Frame;
293
308
}
294
309
 
295
310
///Return the current resolution
296
 
Resolution VideoRenderer::getActiveResolution()
 
311
Resolution VideoRenderer::activeResolution()
297
312
{
298
313
   return m_Res;
299
314
}
300
315
 
 
316
///Get mutex, in case renderer and views are not in the same thread
 
317
QMutex* VideoRenderer::mutex()
 
318
{
 
319
   return m_pMutex;
 
320
}
 
321
 
 
322
 
301
323
/*****************************************************************************
302
324
 *                                                                           *
303
325
 *                                 Setters                                   *