diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0a6cb1152496a1a34ad41e0631195457ade43a1d..3b073fbbc83639e3661228c7745902d2a0134856 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ ADD_DEFINITIONS("-std=c++1y")
 ADD_DEFINITIONS(
    ${QT_DEFINITIONS}
    -fexceptions
+   -O2
 )
 
 PROJECT(ringclient)
diff --git a/src/private/directrenderer.cpp b/src/private/directrenderer.cpp
index a5a2d78d296e2c8bdb8aa7added8d873c91297f9..6fcb1bcb128185621c3e719e0e9762831de35483 100644
--- a/src/private/directrenderer.cpp
+++ b/src/private/directrenderer.cpp
@@ -40,17 +40,13 @@ class DirectRendererPrivate : public QObject
    Q_OBJECT
 public:
    DirectRendererPrivate(Video::DirectRenderer* parent);
-
-   //Attributes
-
 private:
-   Video::DirectRenderer* q_ptr;
-
+//    Video::DirectRenderer* q_ptr;
 };
 
 }
 
-Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent) : QObject(parent), q_ptr(parent)
+Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent) : QObject(parent)/*, q_ptr(parent)*/
 {
 }
 
@@ -67,29 +63,30 @@ Video::DirectRenderer::~DirectRenderer()
 
 void Video::DirectRenderer::startRendering()
 {
-
-    qWarning() << "STARTING RENDERING";
-    setRendering(true);
-    emit started();
+   qWarning() << "STARTING RENDERING";
+   Video::Renderer::d_ptr->m_isRendering = true;
+   emit started();
 }
 void Video::DirectRenderer::stopRendering ()
 {
-    qWarning() << "STOPPING RENDERING";
-    setRendering(false);
-    emit stopped();
+   qWarning() << "STOPPING RENDERING";
+   Video::Renderer::d_ptr->m_isRendering = false;
+   emit stopped();
 }
 
 void Video::DirectRenderer::onNewFrame(const QByteArray& frame)
 {
-//    qDebug("Frame received by DirectRenderer, size: w %d, h %d", size().width(), size().height());
-    if (!isRendering()) {
-       return;
-    }
-    if (static_cast<Video::Renderer*>(this)->d_ptr->otherFrame().size() != (size().height() * size().width()))
-    static_cast<Video::Renderer*>(this)->d_ptr->otherFrame().resize(size().height() * size().width()*4);
-    ::memcpy(static_cast<Video::Renderer*>(this)->d_ptr->otherFrame().data(),frame,static_cast<Video::Renderer*>(this)->d_ptr->otherFrame().size());
-    static_cast<Video::Renderer*>(this)->d_ptr->updateFrameIndex();
-    emit frameUpdated();
+   if (!isRendering()) {
+      return;
+   }
+
+   Video::Renderer::d_ptr->m_pFrame = const_cast<char*>(frame.data());
+   emit frameUpdated();
+}
+
+Video::Renderer::ColorSpace Video::DirectRenderer::colorSpace() const
+{
+   return Video::Renderer::ColorSpace::RGBA;
 }
 
 #include <directrenderer.moc>
diff --git a/src/private/directrenderer.h b/src/private/directrenderer.h
index a71fb06b25a66e5c472ab9bd76da6a5a8bb49f39..db6a2d99dfc528d24a4acb5dbfffa3b55d7d8904 100644
--- a/src/private/directrenderer.h
+++ b/src/private/directrenderer.h
@@ -42,21 +42,24 @@ class LIB_EXPORT DirectRenderer : public Renderer {
    Q_OBJECT
    #pragma GCC diagnostic pop
 
-   public:
+public:
 
-      //Constructor
-      DirectRenderer (const QByteArray& id, const QSize& res);
-      virtual ~DirectRenderer();
+   //Constructor
+   DirectRenderer (const QByteArray& id, const QSize& res);
+   virtual ~DirectRenderer();
 
-      void onNewFrame(const QByteArray& frame);
+   //Getter
+   virtual ColorSpace colorSpace() const override;
 
-  public Q_SLOTS:
-      virtual void startRendering() override;
-      virtual void stopRendering () override;
+   void onNewFrame(const QByteArray& frame);
 
-  private:
-     QScopedPointer<DirectRendererPrivate> d_ptr;
-     Q_DECLARE_PRIVATE(DirectRenderer)
+public Q_SLOTS:
+   virtual void startRendering() override;
+   virtual void stopRendering () override;
+
+private:
+   QScopedPointer<DirectRendererPrivate> d_ptr;
+   Q_DECLARE_PRIVATE(DirectRenderer)
 
 };
 
diff --git a/src/private/shmrenderer.cpp b/src/private/shmrenderer.cpp
index 13e7d63af4fd02f354c79135e98e3972687a3d59..7a422ac4b16d542aba6543f32babb15c3c130c45 100644
--- a/src/private/shmrenderer.cpp
+++ b/src/private/shmrenderer.cpp
@@ -1,6 +1,7 @@
 /****************************************************************************
  *   Copyright (C) 2012-2015 by Savoir-Faire Linux                          *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
+ *   Author : Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
  *                                                                          *
  *   This library is free software; you can redistribute it and/or          *
  *   modify it under the terms of the GNU Lesser General Public             *
@@ -20,7 +21,6 @@
 #include <QtCore/QDebug>
 #include <QtCore/QMutex>
 #include <QtCore/QThread>
-#include <QtCore/QTime>
 
 #include <sys/ipc.h>
 #include <sys/sem.h>
@@ -36,28 +36,35 @@
 #endif
 
 #include <QtCore/QTimer>
+#include <chrono>
+
 #include "private/videorenderermanager.h"
 #include "video/resolution.h"
 #include "private/videorenderer_p.h"
 
+// Uncomment following line to output in console the FPS value
 //#define DEBUG_FPS
-#ifdef DEBUG_FPS
-#include <chrono>
-#endif
 
-///Shared memory object
-struct SHMHeader {
-   sem_t notification;
-   sem_t mutex;
+/* Shared memory object
+ * Implementation note: double-buffering
+ * Shared memory is divided in two regions, each representing one frame.
+ * First byte of each frame is warranted to by aligned on 16 bytes.
+ * One region is marked readable: this region can be safely read.
+ * The other region is writeable: only the producer can use it.
+ */
 
-   unsigned m_BufferGen;
-   int m_BufferSize;
-   /* The header will be aligned on 16-byte boundaries */
-   char padding[8];
+struct SHMHeader {
+   sem_t    mutex        ; /*!< Lock it before any operations on following fields.           */
+   sem_t    frameGenMutex; /*!< unlocked by producer when frameGen modified                  */
+   unsigned frameGen     ; /*!< monotonically incremented when a producer changes readOffset */
+   unsigned frameSize    ; /*!< size in bytes of 1 frame                                     */
+   unsigned mapSize      ; /*!< size to map if you need to see all data                      */
+   unsigned readOffset   ; /*!< offset of readable frame in data                             */
+   unsigned writeOffset  ; /*!< offset of writable frame in data                             */
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-pedantic"
-   char m_Data[];
+   char data[];           /*!< the whole shared memory                                       */
 #pragma GCC diagnostic pop
 };
 
@@ -66,312 +73,287 @@ namespace Video {
 class ShmRendererPrivate : public QObject
 {
    Q_OBJECT
-public:
-   ShmRendererPrivate(Video::ShmRenderer* parent);
-
-   //Attributes
-   QString           m_ShmPath    ;
-   int               fd           ;
-   SHMHeader*        m_pShmArea   ;
-   signed int        m_ShmAreaLen ;
-   uint              m_BufferGen  ;
-   QTimer*           m_pTimer     ;
-   int               m_fpsC       ;
-   int               m_Fps        ;
-   QTime             m_CurrentTime;
-
-#ifdef DEBUG_FPS
-   unsigned          m_frameCount;
-   std::chrono::time_point<std::chrono::system_clock> m_lastFrameDebug;
-#endif
 
-   //Constants
-   static const int TIMEOUT_SEC = 1; // 1 second
-
-   //Helpers
-   timespec createTimeout();
-   bool     shmLock      ();
-   void     shmUnlock    ();
-   bool     renderToBitmap();
+public:
+   ShmRendererPrivate(ShmRenderer* parent);
+
+   //Types
+   using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
+
+   // Attributes
+   QString    m_ShmPath       ;
+   int        m_fd            ;
+   SHMHeader* m_pShmArea      ;
+   unsigned   m_ShmAreaLen    ;
+   uint       m_FrameGen      ;
+   int        m_fpsC          ;
+   int        m_Fps           ;
+   TimePoint  m_lastFrameDebug;
+
+   // Constants
+   constexpr static const int FPS_RATE_SEC        = 1  ;
+   constexpr static const int FRAME_CHECK_RATE_HZ = 120;
+
+   // Helpers
+   timespec createTimeout(           );
+   bool     shmLock      (           );
+   void     shmUnlock    (           );
+   bool     getNewFrame  ( bool wait );
+   bool     remapShm     (           );
 
 private:
    Video::ShmRenderer* q_ptr;
-
-private Q_SLOTS:
-   void timedEvents();
 };
 
-}
-
-Video::ShmRendererPrivate::ShmRendererPrivate(Video::ShmRenderer* parent) : QObject(parent), q_ptr(parent),
-   fd(-1),m_fpsC(0),m_Fps(0),
-   m_pShmArea((SHMHeader*)MAP_FAILED), m_ShmAreaLen(0), m_BufferGen(0),
-   m_pTimer(nullptr)
+ShmRendererPrivate::ShmRendererPrivate(ShmRenderer* parent)
+   : QObject     ( parent                              )
+   , q_ptr       ( parent                              )
+   , m_fd        ( -1                                  )
+   , m_fpsC      ( 0                                   )
+   , m_Fps       ( 0                                   )
+   , m_pShmArea  ( (SHMHeader*)MAP_FAILED              )
+   , m_ShmAreaLen( 0                                   )
+   , m_FrameGen  ( 0                                   )
 #ifdef DEBUG_FPS
-   , m_frameCount(0)
-   , m_lastFrameDebug(std::chrono::system_clock::now())
+   , m_frameCount( 0                                   )
+   , m_lastFrameDebug(std::chrono::system_clock::now() )
 #endif
 {
 }
 
-///Constructor
-Video::ShmRenderer::ShmRenderer(const QByteArray& id, const QString& shmPath, const QSize& res): Renderer(id, res), d_ptr(new ShmRendererPrivate(this))
+/// Constructor
+ShmRenderer::ShmRenderer(const QByteArray& id, const QString& shmPath, const QSize& res)
+   : Renderer(id, res)
+   , d_ptr(new ShmRendererPrivate(this))
 {
    d_ptr->m_ShmPath = shmPath;
    setObjectName("Video::Renderer:"+id);
 }
 
-///Destructor
-Video::ShmRenderer::~ShmRenderer()
+/// Destructor
+ShmRenderer::~ShmRenderer()
 {
    stopShm();
-   //delete m_pShmArea;
 }
 
-///Get the data from shared memory and transform it into a QByteArray
-bool Video::ShmRendererPrivate::renderToBitmap()
+/// Wait new frame data from shared memory and save pointer
+bool ShmRendererPrivate::getNewFrame(bool wait)
 {
-   QMutexLocker locker {q_ptr->mutex()};
-
-#ifdef Q_OS_LINUX
-   if (!q_ptr->isRendering())
-      return false;
-
    if (!shmLock())
       return false;
 
-   if (m_BufferGen == m_pShmArea->m_BufferGen) {
-	   // wait for a new buffer
-	   do {
-		   shmUnlock();
-		   auto err = sem_trywait(&m_pShmArea->notification);
-		   if (!err)
-			   break;
+   if (m_FrameGen == m_pShmArea->frameGen) {
+      shmUnlock();
 
-		   // Fatal error?
-		   if (errno != EAGAIN)
-			   return false;
+      if (not wait)
+         return false;
 
-		   // wait a little bit that deamon does its work
-		   usleep(10); // must be less than the maximal framerate possible
+      // wait for a new frame, max 33ms
+      static const struct timespec timeout = {0, 33000000};
+      if (::sem_timedwait(&m_pShmArea->frameGenMutex, &timeout) < 0)
+         return false;
 
-           // stopRendering called?
-           if (!q_ptr->isRendering())
-               return false;
-	   } while (m_BufferGen == m_pShmArea->m_BufferGen);
+      if (!shmLock())
+         return false;
 
-	   if (!shmLock())
-		   return false;
    }
 
-   if (!q_ptr->resizeShm()) {
+   // valid frame to render (daemon may have stopped)?
+   if (! m_pShmArea->frameSize) {
+      shmUnlock();
+      return false;
+   }
+
+   // map frame data
+   if (!remapShm()) {
       qDebug() << "Could not resize shared memory";
-	  shmUnlock();
       return false;
    }
 
-   if (static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().size() != m_pShmArea->m_BufferSize)
-      static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().resize(m_pShmArea->m_BufferSize);
-   memcpy(static_cast<Video::Renderer*>(q_ptr)->d_ptr->otherFrame().data(),m_pShmArea->m_Data,m_pShmArea->m_BufferSize);
-   m_BufferGen = m_pShmArea->m_BufferGen;
-   static_cast<Video::Renderer*>(q_ptr)->d_ptr->updateFrameIndex();
+   q_ptr->Video::Renderer::d_ptr->m_pFrame    = (char*)(m_pShmArea->data + m_pShmArea->readOffset);
+   m_FrameGen                                 = m_pShmArea->frameGen;
+   q_ptr->Video::Renderer::d_ptr->m_FrameSize = m_pShmArea->frameSize;
+
    shmUnlock();
 
+   ++m_fpsC;
+
+   // Compute the FPS shown to the client
+   auto currentTime = std::chrono::system_clock::now();
+   const std::chrono::duration<double> seconds = currentTime - m_lastFrameDebug;
+   if (seconds.count() >= FPS_RATE_SEC) {
+      m_Fps = m_fpsC / seconds.count();
+      m_fpsC = 0;
+      m_lastFrameDebug = currentTime;
 #ifdef DEBUG_FPS
-    auto currentTime = std::chrono::system_clock::now();
-    const std::chrono::duration<double> seconds = currentTime - m_lastFrameDebug;
-    ++m_frameCount;
-    if (seconds.count() > 1) {
-        qDebug() << this << ": FPS " << (m_frameCount / seconds.count());
-        m_frameCount = 0;
-        m_lastFrameDebug = currentTime;
-    }
+      qDebug() << this << ": FPS " << m_fps;
 #endif
+   }
 
+   emit q_ptr->frameUpdated();
    return true;
-#else
-   return false;
-#endif
 }
 
-///Connect to the shared memory
-bool Video::ShmRenderer::startShm()
+/// Remap the shared memory
+/// Shared memory in unlocked state if returns false (resize failed).
+bool ShmRendererPrivate::remapShm()
 {
-   if (d_ptr->fd != -1) {
+   // This loop handles case where deamon resize shared memory
+   // during time we unlock it for remapping.
+   while (m_ShmAreaLen != m_pShmArea->mapSize) {
+      auto mapSize = m_pShmArea->mapSize;
+      shmUnlock();
+
+      if (::munmap(m_pShmArea, m_ShmAreaLen)) {
+         qDebug() << "Could not unmap shared area: " << strerror(errno);
+         return false;
+      }
+
+      m_pShmArea = (SHMHeader*) ::mmap(nullptr, mapSize, PROT_READ | PROT_WRITE,
+                                       MAP_SHARED, m_fd, 0);
+
+      if (m_pShmArea == MAP_FAILED) {
+         qDebug() << "Could not remap shared area: " << strerror(errno);
+         return false;
+      }
+
+      if (!shmLock())
+         return false;
+
+      m_ShmAreaLen = mapSize;
+   }
+
+   return true;
+}
+
+/// Connect to the shared memory
+bool ShmRenderer::startShm()
+{
+   if (d_ptr->m_fd != -1) {
       qDebug() << "fd must be -1";
       return false;
    }
 
-   d_ptr->fd = shm_open(d_ptr->m_ShmPath.toLatin1(), O_RDWR, 0);
-   if (d_ptr->fd < 0) {
-      qDebug() << "could not open shm area " << d_ptr->m_ShmPath << ", shm_open failed:" << strerror(errno);
+   d_ptr->m_fd = ::shm_open(d_ptr->m_ShmPath.toLatin1(), O_RDWR, 0);
+
+   if (d_ptr->m_fd < 0) {
+      qDebug() << "could not open shm area" << d_ptr->m_ShmPath
+               << ", shm_open failed:"      << strerror(errno);
       return false;
    }
-   d_ptr->m_ShmAreaLen = sizeof(SHMHeader);
-   #pragma GCC diagnostic push
-   #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
-   d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, d_ptr->m_ShmAreaLen, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0);
-   #pragma GCC diagnostic pop
+
+   // Map only header data
+   const auto mapSize = sizeof(SHMHeader);
+   d_ptr->m_pShmArea = (SHMHeader*) ::mmap(nullptr, mapSize,
+      PROT_READ | PROT_WRITE,
+      MAP_SHARED, d_ptr->m_fd, 0
+   );
+
    if (d_ptr->m_pShmArea == MAP_FAILED) {
-      qDebug() << "Could not map shm area, mmap failed";
+      qDebug() << "Could not remap shared area";
       return false;
    }
-   emit started();
-   return true;
-}
-
-///Disconnect from the shared memory
-void Video::ShmRenderer::stopShm()
-{
-   if (d_ptr->fd >= 0)
-      close(d_ptr->fd);
-   d_ptr->fd = -1;
 
-   if (d_ptr->m_pShmArea != MAP_FAILED)
-      munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen);
-   d_ptr->m_ShmAreaLen = 0;
-   d_ptr->m_pShmArea = (SHMHeader*) MAP_FAILED;
+   d_ptr->m_ShmAreaLen = mapSize;
+   return true;
 }
 
-///Resize the shared memory
-bool Video::ShmRenderer::resizeShm()
+/// Disconnect from the shared memory
+void ShmRenderer::stopShm()
 {
-   while (( (unsigned int) sizeof(SHMHeader) + (unsigned int) d_ptr->m_pShmArea->m_BufferSize) > (unsigned int) d_ptr->m_ShmAreaLen) {
-      const size_t new_size = sizeof(SHMHeader) + d_ptr->m_pShmArea->m_BufferSize;
-
-      d_ptr->shmUnlock();
-      if (munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen)) {
-            qDebug() << "Could not unmap shared area:" << strerror(errno);
-            return false;
-      }
+   if (d_ptr->m_fd < 0)
+      return;
 
-      #pragma GCC diagnostic push
-      #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
-      d_ptr->m_pShmArea = (SHMHeader*) mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, d_ptr->fd, 0);
-      #pragma GCC diagnostic pop
-      d_ptr->m_ShmAreaLen = new_size;
+   ::close(d_ptr->m_fd);
+   d_ptr->m_fd = -1;
 
-      if (!d_ptr->m_pShmArea) {
-            d_ptr->m_pShmArea = nullptr;
-            qDebug() << "Could not remap shared area";
-            return false;
-      }
+   if (d_ptr->m_pShmArea == MAP_FAILED)
+      return;
 
-      d_ptr->m_ShmAreaLen = new_size;
-      if (!d_ptr->shmLock())
-            return true;
-   }
-   return true;
+   ::munmap(d_ptr->m_pShmArea, d_ptr->m_ShmAreaLen);
+   d_ptr->m_ShmAreaLen = 0;
+   d_ptr->m_pShmArea = (SHMHeader*) MAP_FAILED;
 }
 
-///Lock the memory while the copy is being made
-bool Video::ShmRendererPrivate::shmLock()
+/// Lock the memory while the copy is being made
+bool ShmRendererPrivate::shmLock()
 {
-#ifdef Q_OS_LINUX
-   return sem_trywait(&m_pShmArea->mutex) >= 0;
-#else
-   return false;
-#endif
+   return ::sem_wait(&m_pShmArea->mutex) >= 0;
 }
 
-///Remove the lock, allow a new frame to be drawn
-void Video::ShmRendererPrivate::shmUnlock()
+/// Remove the lock, allow a new frame to be drawn
+void ShmRendererPrivate::shmUnlock()
 {
-#ifdef Q_OS_LINUX
-   sem_post(&m_pShmArea->mutex);
-#endif
+   ::sem_post(&m_pShmArea->mutex);
 }
 
-
 /*****************************************************************************
  *                                                                           *
  *                                   Slots                                   *
  *                                                                           *
  ****************************************************************************/
 
-///Update the buffer
-void Video::ShmRendererPrivate::timedEvents()
-{
-   if (renderToBitmap()) {
-      //Compute the FPS shown to the client
-      if (m_CurrentTime.second() != QTime::currentTime().second()) {
-         m_Fps = m_fpsC;
-         m_fpsC=0;
-         m_CurrentTime = QTime::currentTime();
-      }
-      m_fpsC++;
-
-      emit q_ptr->frameUpdated();
-   }
-   /*else {
-      qDebug() << "Frame dropped";
-      usleep(rand()%1000); //Be sure it can come back in sync
-   }*/
-}
-
-///Start the rendering loop
-void Video::ShmRenderer::startRendering()
+/// Start the rendering loop
+void ShmRenderer::startRendering()
 {
    QMutexLocker locker {mutex()};
 
-   if (!startShm()) {
-      qDebug() << "Cannot start rendering on " << d_ptr->m_ShmPath;
+   if (!startShm())
       return;
-   }
-
-   if (!d_ptr->m_pTimer) {
-      d_ptr->m_pTimer = new QTimer(nullptr);
 
-//       m_pTimer->moveToThread(thread());
-      connect(d_ptr->m_pTimer,SIGNAL(timeout()),d_ptr.data(),SLOT(timedEvents()));
-      d_ptr->m_pTimer->setInterval(30);
-   }
-
-   if (!d_ptr->m_pTimer->isActive()) {
-      qDebug() << "Is running" << thread()->isRunning();
-      d_ptr->m_pTimer->start();
-   }
-   else
-      qDebug() << "Timer already started!";
-
-   setRendering(true);
+   Video::Renderer::d_ptr->m_isRendering = true;
+   emit started();
 }
 
-///Stop the rendering loop
-void Video::ShmRenderer::stopRendering()
+/// Stop the rendering loop
+void ShmRenderer::stopRendering()
 {
-   setRendering(false);
-
    QMutexLocker locker {mutex()};
-   qDebug() << "Stopping rendering on" << this;
-   if (d_ptr->m_pTimer)
-      d_ptr->m_pTimer->stop();
+   Video::Renderer::d_ptr->m_isRendering = false;
+
    emit stopped();
    stopShm();
 }
 
-
 /*****************************************************************************
  *                                                                           *
  *                                 Getters                                   *
  *                                                                           *
  ****************************************************************************/
 
-///Get the current frame rate of this renderer
-int Video::ShmRenderer::fps() const
+/// Get the current frame rate of this renderer
+int ShmRenderer::fps() const
 {
    return d_ptr->m_Fps;
 }
 
+/// Get frame data pointer from shared memory
+const QByteArray& ShmRenderer::currentFrame() const
+{
+   if (!isRendering())
+      return Renderer::currentFrame();
+
+   QMutexLocker lk {mutex()};
+   d_ptr->getNewFrame(false);
+   return Renderer::currentFrame();
+}
+
+Video::Renderer::ColorSpace ShmRenderer::colorSpace() const
+{
+   return Video::Renderer::ColorSpace::BGRA;
+}
+
 /*****************************************************************************
  *                                                                           *
  *                                 Setters                                   *
  *                                                                           *
  ****************************************************************************/
 
-void Video::ShmRenderer::setShmPath(const QString& path)
+void ShmRenderer::setShmPath(const QString& path)
 {
    d_ptr->m_ShmPath = path;
 }
 
+} // namespace Video
+
 #include <shmrenderer.moc>
diff --git a/src/private/shmrenderer.h b/src/private/shmrenderer.h
index 39bb2669c44a6ca3eb662471a107c779bfb928da..63e042d209db3533dddd353ae8996752baaa376b 100644
--- a/src/private/shmrenderer.h
+++ b/src/private/shmrenderer.h
@@ -42,32 +42,32 @@ class LIB_EXPORT ShmRenderer : public Renderer {
    Q_OBJECT
    #pragma GCC diagnostic pop
 
-   public:
-      //Constructor
-      ShmRenderer (const QByteArray& id, const QString& shmPath, const QSize& res);
-      virtual ~ShmRenderer();
+   friend class VideoRendererManagerPrivate ;
 
-      //Mutators
-      bool resizeShm();
-      void stopShm  ();
-      bool startShm ();
+public:
+   //Constructor
+   ShmRenderer (const QByteArray& id, const QString& shmPath, const QSize& res);
+   virtual ~ShmRenderer();
 
-      //Getters
-      virtual int fps             () const         ;
+   //Mutators
+   void stopShm  ();
+   bool startShm ();
 
-      //Setters
-      void setShmPath   (const QString& path);
-
-   private:
-      QScopedPointer<ShmRendererPrivate> d_ptr;
-      Q_DECLARE_PRIVATE(ShmRenderer)
-
-   public Q_SLOTS:
-      void startRendering();
-      void stopRendering ();
+   //Getters
+   int fps() const;
+   virtual const QByteArray& currentFrame() const override;
+   virtual ColorSpace        colorSpace  () const override;
 
+   //Setters
+   void setShmPath(const QString& path);
 
+private:
+   QScopedPointer<ShmRendererPrivate> d_ptr;
+   Q_DECLARE_PRIVATE(ShmRenderer)
 
+public Q_SLOTS:
+   void startRendering();
+   void stopRendering ();
 };
 
 }
diff --git a/src/private/videorenderer_p.h b/src/private/videorenderer_p.h
index 6770d5e57ec07b296a3e90936fb309d6d364446c..27d574ee569cc5b4f885b76abc8207a76d7cf214 100644
--- a/src/private/videorenderer_p.h
+++ b/src/private/videorenderer_p.h
@@ -38,15 +38,12 @@ public:
 
    //Attributes
    std::atomic_bool  m_isRendering;
-   QByteArray        m_Frame[2]   ;
-   bool              m_FrameIdx   ;
    QMutex*           m_pMutex     ;
    QString           m_Id         ;
    QSize             m_pSize      ;
-
-   //Helpers
-   QByteArray& otherFrame       ()      ;
-   void        updateFrameIndex ()      ;
+   char*             m_pFrame     ;
+   QByteArray        m_Content    ;
+   unsigned int      m_FrameSize  ;
 
 private:
    Video::Renderer* q_ptr;
diff --git a/src/private/videorenderermanager.cpp b/src/private/videorenderermanager.cpp
index 602404cf64f4c15f00eebb867e0cfa097c654c98..309beb52f7a5410a26da006a3c5f9bd6d6b1b113 100644
--- a/src/private/videorenderermanager.cpp
+++ b/src/private/videorenderermanager.cpp
@@ -36,6 +36,7 @@
 #include <video/resolution.h>
 #include "private/videorate_p.h"
 #include "private/call_p.h"
+#include "private/videorenderer_p.h"
 
 #ifdef ENABLE_LIBWRAP
  #include "private/directrenderer.h"
diff --git a/src/private/videorenderermanager.h b/src/private/videorenderermanager.h
index 9e0edb325a7d0bac176ea65ef86aa971160f16d4..2cf14aedb4ec1599aba3fa61ec0c913936f5bbb1 100644
--- a/src/private/videorenderermanager.h
+++ b/src/private/videorenderermanager.h
@@ -37,7 +37,8 @@ struct SHMHeader;
 class VideoRendererManagerPrivate;
 
 ///VideoModel: Video event dispatcher
-class VideoRendererManager : public QObject {
+class VideoRendererManager : public QObject
+{
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
    Q_OBJECT
diff --git a/src/video/renderer.cpp b/src/video/renderer.cpp
index d6ae913a60010fc6d8b6a4e108789ee2cfec4615..e67668e196bf0f8631c78d04f96ebba7d292fcf3 100644
--- a/src/video/renderer.cpp
+++ b/src/video/renderer.cpp
@@ -23,20 +23,24 @@
 //Qt
 #include <QtCore/QMutex>
 
-Video::RendererPrivate::RendererPrivate(Video::Renderer* parent) : QObject(parent), q_ptr(parent),
-m_pMutex(new QMutex()), m_FrameIdx(false)
+Video::RendererPrivate::RendererPrivate(Video::Renderer* parent)
+   : QObject(parent), q_ptr(parent)
+   , m_pMutex(new QMutex()),m_pFrame(nullptr),m_FrameSize(0),m_isRendering(false)
 {
 }
 
 Video::Renderer::Renderer(const QByteArray& id, const QSize& res) : d_ptr(new RendererPrivate(this))
 {
    setObjectName("Renderer:"+id);
-   d_ptr->m_pSize = res;
-   d_ptr->m_Id = id;
+   d_ptr->m_FrameSize = res.width() * res.height() * 4;
+   d_ptr->m_pSize     = res;
+   d_ptr->m_Id        = id;
 }
 
 Video::Renderer::~Renderer()
-{}
+{
+   delete d_ptr;
+}
 
 /*****************************************************************************
 *                                                                           *
@@ -44,24 +48,12 @@ Video::Renderer::~Renderer()
 *                                                                           *
 ****************************************************************************/
 
+///Return if the rendering is currently active or not
 bool Video::Renderer::isRendering() const
 {
   return d_ptr->m_isRendering;
 }
 
-QByteArray& Video::RendererPrivate::otherFrame()
-{
-  static QByteArray empty;
-  return q_ptr->isRendering()?m_Frame[!m_FrameIdx]:empty;
-}
-
-///Return the current framerate
-const QByteArray& Video::Renderer::currentFrame() const
-{
-  static QByteArray empty;
-  return isRendering()?d_ptr->m_Frame[d_ptr->m_FrameIdx]:empty;
-}
-
 ///Get mutex, in case renderer and views are not in the same thread
 QMutex* Video::Renderer::mutex() const
 {
@@ -74,26 +66,22 @@ QSize Video::Renderer::size() const
   return d_ptr->m_pSize;
 }
 
+const QByteArray& Video::Renderer::currentFrame() const
+{
+   if (d_ptr->m_pFrame && d_ptr->m_FrameSize)
+      d_ptr->m_Content.setRawData(d_ptr->m_pFrame,d_ptr->m_FrameSize);
+   return d_ptr->m_Content;
+}
+
 /*****************************************************************************
  *                                                                           *
  *                                 Setters                                   *
  *                                                                           *
  ****************************************************************************/
 
-///Return the current resolution
-void Video::Renderer::setRendering(bool rendering) const
-{
-  d_ptr->m_isRendering = rendering;
-}
-
 void Video::Renderer::setSize(const QSize& size) const
 {
   d_ptr->m_pSize = size;
 }
 
-void Video::RendererPrivate::updateFrameIndex()
-{
-   m_FrameIdx = !m_FrameIdx;
-}
-
 #include <renderer.moc>
diff --git a/src/video/renderer.h b/src/video/renderer.h
index aa5f6548551fa8cd2ba90ee45abbf85ac9b76854..a2db70f00f71b6b4b569360659f9d7107833e5cd 100644
--- a/src/video/renderer.h
+++ b/src/video/renderer.h
@@ -33,6 +33,7 @@ namespace Video {
 
 class RendererPrivate;
 class ShmRendererPrivate;
+class ShmRenderer;
 class DirectRendererPrivate;
 class DirectRenderer;
 
@@ -43,17 +44,30 @@ class DirectRenderer;
  *
  * Each platform transparently provide its own implementation.
  */
-class LIB_EXPORT Renderer : public QObject {
+class LIB_EXPORT Renderer : public QObject
+{
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
-Q_OBJECT
+   Q_OBJECT
 #pragma GCC diagnostic pop
 
-friend class Video::ShmRendererPrivate;
-friend class Video::DirectRendererPrivate;
-friend class Video::DirectRenderer;
+   friend class Video::ShmRendererPrivate   ;
+   friend class Video::ShmRenderer          ;
+   friend class Video::DirectRendererPrivate;
+   friend class Video::DirectRenderer       ;
+   friend class VideoRendererManagerPrivate ;
 
 public:
+
+   /**
+    * Each platform may have its preferred color space. To be able to use a
+    * client on multiple platforms, they need to check the colorspace.
+    */
+   enum class ColorSpace {
+      BGRA , /*!< 32bit BLUE  GREEN RED ALPHA */
+      RGBA , /*!< 32bit ALPHA GREEN RED BLUE  */
+   };
+
    //Constructor
    Renderer (const QByteArray& id,  const QSize& res);
    virtual ~Renderer();
@@ -63,14 +77,12 @@ public:
    virtual const QByteArray& currentFrame    () const;
    virtual QSize             size            () const;
    virtual QMutex*           mutex           () const;
+   virtual ColorSpace        colorSpace      () const = 0;
 
-   //Setters
-   void setRendering(bool rendering)            const;
-   void setSize(const QSize& size)              const;
+   void setSize(const QSize& size) const;
 
 Q_SIGNALS:
-   ///Emitted when a new frame is ready
-   void frameUpdated();
+   void frameUpdated(); // Emitted when a new frame is ready
    void stopped     ();
    void started     ();
 
@@ -78,9 +90,8 @@ public Q_SLOTS:
    virtual void startRendering() = 0;
    virtual void stopRendering () = 0;
 
-
 private:
-   QScopedPointer<RendererPrivate> d_ptr;
+   RendererPrivate* d_ptr;
    Q_DECLARE_PRIVATE(Renderer)
 
 };