diff --git a/CMakeLists.txt b/CMakeLists.txt
index 775097eb677f132e4face9fe5e14e2db756aa496..24f6e8505c6e60a004747f84e17bbe5c7820f7f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -275,7 +275,6 @@ ENDIF()
 SET( libringclient_LIB_SRCS
   #Data objects
   src/uri.cpp
-  src/video/renderer.cpp
 
   #Models
   src/contactmodel.cpp
@@ -292,9 +291,6 @@ SET( libringclient_LIB_SRCS
   src/callbackshandler.cpp
   src/behaviorcontroller.cpp
   src/datatransfermodel.cpp
-  src/newvideo.cpp
-  src/shmrenderer.cpp
-  src/directrenderer.cpp
   src/messagelistmodel.cpp
 
   #Communication
@@ -327,8 +323,6 @@ SET( libringclient_LIB_HDRS
   src/smartinfohub.h
   src/vcard.h
   src/namedirectory.h
-  src/shmrenderer.h
-  src/directrenderer.h
   src/messagelistmodel.h
 )
 
@@ -353,7 +347,7 @@ SET(libringclient_api_LIB_HDRS
   src/api/behaviorcontroller.h
   src/api/datatransfermodel.h
   src/api/datatransfer.h
-  src/api/newvideo.h
+  src/api/video.h
 )
 
 SET(libringclient_WEB_chatview
@@ -375,11 +369,6 @@ SET(libringclient_WEB_chatview
    src/web-chatview/web.gresource.xml
 )
 
-SET(libringclient_video_LIB_HDRS
-  src/video/renderer.h
-  #The renderer implementations are not exported on purpose
-)
-
 SET(libringclient_interface_LIB_HDRS
   src/interfaces/pixmapmanipulatori.h
   src/interfaces/dbuserrorhandleri.h
@@ -390,6 +379,17 @@ SET( libringclient_extra_LIB_HDRS
   src/containerview.h
 )
 
+# video
+list(APPEND libringclient_video_LIB_HDRS src/renderer.h)
+list(APPEND libringclient_LIB_SRCS src/renderer.cpp)
+if(ENABLE_LIBWRAP)
+   list(APPEND libringclient_video_LIB_HDRS src/directrenderer.h)
+   list(APPEND libringclient_LIB_SRCS src/directrenderer.cpp)
+else()
+   list(APPEND libringclient_video_LIB_HDRS src/shmrenderer.h)
+   list(APPEND libringclient_LIB_SRCS src/shmrenderer.cpp)
+endif()
+
 IF(${ENABLE_LIBWRAP} MATCHES true OR ${ENABLE_TEST} MATCHES true)
    # done this way because of bug in cmake 2.8
    # (not necessary in 3.0+)
@@ -497,7 +497,6 @@ ENDIF()
 SET(libringclient_PRIVATE_HDRS
    src/private/namedirectory_p.h
    src/private/smartInfoHub_p.h
-   src/private/videorenderer_p.h
 )
 
 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true)
@@ -537,6 +536,17 @@ IF(NOT ${ENABLE_STATIC} MATCHES false)
     )
 ENDIF()
 
+# For avframe dependency on Windows/macOS.
+if(NOT DEFINED LIBAV_INCLUDE_PATH)
+   set(LIBJAMI_CONTRIB_DIR "${PROJECT_SOURCE_DIR}/../daemon/contrib/")
+   if(WIN32)
+      set(LIBAV_INCLUDE_PATH ${LIBJAMI_CONTRIB_DIR}/build/ffmpeg/Build/win32/x64/include/)
+   else()
+      set(LIBAV_INCLUDE_PATH ${LIBJAMI_CONTRIB_DIR}/native/ffmpeg)
+   endif()
+endif()
+include_directories(${LIBAV_INCLUDE_PATH})
+
 if (ENABLE_SHARED)
     message(STATUS "Configuring as shared lib")
     add_library(ringclient SHARED ${libringclient_LIB_SRCS} ${libringclient_api_LIB_HDRS} ${LIB_HEADER_MOC} )
diff --git a/src/api/avmodel.h b/src/api/avmodel.h
index 26ff74bc92a208a59585ecad3a83d76f65bc39fc..f76d1682c0575577433a64301de1a4ed4ab38313 100644
--- a/src/api/avmodel.h
+++ b/src/api/avmodel.h
@@ -1,35 +1,33 @@
-/****************************************************************************
- *    Copyright (C) 2018-2022 Savoir-faire Linux Inc.                       *
- *   Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>             *
- *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
+/*
+ *  Copyright (C) 2018-2022 Savoir-faire Linux Inc.
+ *  Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #pragma once
 
-// std
+#include "api/video.h"
+#include "typedefs.h"
+
+#include <QObject>
+
 #include <memory>
 #include <string>
 #include <vector>
 
-// Qt
-#include <qobject.h>
-
-// LRC
-#include "api/newvideo.h"
-#include "typedefs.h"
-
 namespace lrc {
 
 class CallbacksHandler;
@@ -246,23 +244,12 @@ public:
      * @param resource
      */
     Q_INVOKABLE void stopPreview(const QString& resource);
-    /**
-     * Get a renderer from a call
-     * @param id the callid or "local"
-     * @return the linked renderer
-     * @throw std::out_of_range if not found
-     */
-    const video::Renderer& getRenderer(const QString& id) const;
     /**
      * Get the list of available windows ids
      * X11: a id is of the form 0x0000000
      * @return map with windows names and ids
      */
     const QVariantMap getListWindows() const;
-    /**
-     * set to true to receive AVFrames from render
-     */
-    void useAVFrame(bool useAVFrame);
     /**
      * set current using device
      * @param device name
@@ -277,22 +264,18 @@ public:
      * clear current using device
      */
     void clearCurrentVideoCaptureDevice();
-
     /**
-     * Add video::Renderer to renderers_ and start it
+     * Add Renderer to renderers_ and start it
      * @param id
      * @param settings
      * @param shmPath
      */
-    void addRenderer(const QString& id,
-                     const video::Settings& settings,
-                     const QString& shmPath = {});
+    void addRenderer(const QString& id, const QSize& res, const QString& shmPath = {});
 
-    /**
-     * Remove renderer from renderers_
-     * @param id
-     */
-    void removeRenderer(const QString& id);
+    bool hasRenderer(const QString& id);
+    QSize getRendererSize(const QString& id);
+    video::Frame getRendererFrame(const QString& id);
+    bool useDirectRenderer() const;
 
 Q_SIGNALS:
     /**
@@ -305,6 +288,11 @@ Q_SIGNALS:
      * @param id of the renderer
      */
     void rendererStopped(const QString& id);
+    /**
+     * Emitted when a new frame is requested
+     * @param id
+     */
+    void frameBufferRequested(const QString& id, AVFrame* frame);
     /**
      * Emitted when a new frame is ready
      * @param id
diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h
index b7bdf539983c8f60f1fae47614bbc0a8fa05e613..6c786f11486aaaf9b3136033d3e1716d6182de5f 100644
--- a/src/api/newcallmodel.h
+++ b/src/api/newcallmodel.h
@@ -21,7 +21,7 @@
 #include "api/behaviorcontroller.h"
 #include "api/call.h"
 #include "api/account.h"
-#include "api/newvideo.h"
+#include "api/video.h"
 #include "typedefs.h"
 
 #include <QObject>
@@ -29,10 +29,6 @@
 #include <memory>
 #include <map>
 
-namespace Video {
-class Renderer;
-}
-
 namespace lrc {
 
 class CallbacksHandler;
diff --git a/src/api/newvideo.h b/src/api/newvideo.h
deleted file mode 100644
index f076c715e385d687f6c08d0b682a4a4f401f2cd7..0000000000000000000000000000000000000000
--- a/src/api/newvideo.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/****************************************************************************
- *    Copyright (C) 2018-2022 Savoir-faire Linux Inc.                       *
- *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#pragma once
-
-// Std
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-// Qt
-#include <qobject.h>
-
-// Lrc
-#include "typedefs.h"
-
-// Qt
-#include <QObject>
-#include <QThread>
-
-struct AVFrame;
-
-namespace lrc {
-
-class RendererPimpl;
-
-namespace api {
-
-namespace video {
-Q_NAMESPACE
-Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
-
-constexpr static const char PREVIEW_RENDERER_ID[] = "local";
-
-using Channel = QString;
-using Resolution = QString;
-using Framerate = float;
-using FrameratesList = QVector<Framerate>;
-using ResRateList = QVector<QPair<Resolution, FrameratesList>>;
-using Capabilities = QMap<Channel, ResRateList>;
-
-/**
- * This class is used by Renderer class to expose video data frame
- * that could be owned by instances of this class or shared.
- * If an instance carries data, "storage.size()" is greater than 0
- * and equals to "size", "ptr" is equals to "storage.data()".
- * If shared data is carried, only "ptr" and "size" are set.
- */
-struct Frame
-{
-    uint8_t* ptr {nullptr};
-    std::size_t size {0};
-    std::vector<uint8_t> storage {};
-    // Next variables are currently used with DirectRenderer only
-    unsigned int height {0};
-    unsigned int width {0};
-};
-
-enum class DeviceType { CAMERA, DISPLAY, FILE, INVALID };
-Q_ENUM_NS(DeviceType)
-
-/**
- * This class describes the current rendered device
- */
-struct RenderedDevice
-{
-    QString name;
-    DeviceType type = DeviceType::INVALID;
-};
-
-/**
- * This class describes current video settings
- */
-struct Settings
-{
-    Channel channel = "";
-    QString name = "";
-    QString id = "";
-    Framerate rate = 0;
-    Resolution size = "";
-};
-
-class LIB_EXPORT Renderer : public QObject
-{
-    Q_OBJECT
-public:
-    Renderer(const QString& id,
-             Settings videoSettings,
-             const QString& shmPath = "",
-             const bool useAVFrame = false);
-    ~Renderer();
-
-    /**
-     * Update size and shmPath of a renderer
-     * @param res new resolution "wxh"
-     * @param shmPath new shmPath
-     */
-    void update(const QString& res, const QString& shmPath);
-
-    // Getters
-    /**
-     * @return if renderer is rendering
-     */
-    bool isRendering() const;
-    /**
-     * @return renderer's id
-     */
-    QString getId() const;
-    /**
-     * @return current rendered frame
-     */
-    Frame currentFrame() const;
-
-#if defined(ENABLE_LIBWRAP)
-    /**
-     * @return current avframe
-     */
-    std::unique_ptr<AVFrame, void (*)(AVFrame*)> currentAVFrame() const;
-#endif
-
-    /**
-     * @return current size
-     */
-    QSize size() const; // TODO convert into std format!
-
-    // Utils
-    /**
-     * set to true to receive AVFrames from render
-     */
-    void useAVFrame(bool useAVFrame);
-
-    bool useDirectRenderer() const;
-
-Q_SIGNALS:
-    /**
-     * Emitted when a new frame is ready
-     * @param id
-     */
-    void frameUpdated(const QString& id);
-    void started(const QString& id);
-    void stopped(const QString& id);
-
-    /**
-     * Start rendering
-     */
-    void startRendering();
-    /**
-     * Stop rendering
-     */
-    void stopRendering();
-
-private:
-    std::unique_ptr<RendererPimpl> pimpl_;
-};
-
-} // namespace video
-} // namespace api
-} // namespace lrc
diff --git a/src/api/video.h b/src/api/video.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d44c0241fd2b08277d274e0ffd4e8d457af89c4
--- /dev/null
+++ b/src/api/video.h
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2018-2022 Savoir-faire Linux Inc.
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "typedefs.h"
+
+#include <QObject>
+#include <QPair>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+extern "C" {
+#include <libavutil/frame.h>
+}
+
+namespace lrc {
+namespace api {
+namespace video {
+Q_NAMESPACE
+Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+
+constexpr static const char PREVIEW_RENDERER_ID[] = "local";
+
+using Channel = QString;
+using Resolution = QString;
+using Framerate = float;
+using FrameratesList = QVector<Framerate>;
+using ResRateList = QVector<QPair<Resolution, FrameratesList>>;
+using Capabilities = QMap<Channel, ResRateList>;
+
+// This class is used to expose video data frame(currently only
+// by the ShmRenderer class).
+struct Frame
+{
+    // Used by SHM renderer.
+    uint8_t* ptr {nullptr};
+    size_t size {0};
+};
+
+enum class DeviceType { CAMERA, DISPLAY, FILE, INVALID };
+Q_ENUM_NS(DeviceType)
+
+// This class describes the current video input device.
+struct RenderedDevice
+{
+    QString name;
+    DeviceType type = DeviceType::INVALID;
+};
+
+// This class describes current video settings
+struct Settings
+{
+    Channel channel = "";
+    QString name = "";
+    QString id = "";
+    Framerate rate = 0;
+    Resolution size = "";
+};
+} // namespace video
+} // namespace api
+} // namespace lrc
diff --git a/src/avmodel.cpp b/src/avmodel.cpp
index ebf5eeb281b8cf3d6c905bc67029a47cf5d54b11..3c70d6e28abebbf92707db211882b294ead5f6bb 100644
--- a/src/avmodel.cpp
+++ b/src/avmodel.cpp
@@ -1,24 +1,45 @@
-/****************************************************************************
- *    Copyright (C) 2018-2022 Savoir-faire Linux Inc.                       *
- *   Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>             *
- *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
+/*
+ *  Copyright (C) 2018-2022 Savoir-faire Linux Inc.
+ *  Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #include "api/avmodel.h"
 
-// Std
+#include "api/video.h"
+#include "api/call.h"
+#include "api/lrc.h"
+#ifdef ENABLE_LIBWRAP
+#include "directrenderer.h"
+#else
+#include "shmrenderer.h"
+#endif
+#include "callbackshandler.h"
+#include "dbus/callmanager.h"
+#include "dbus/configurationmanager.h"
+#include "dbus/videomanager.h"
+#include "authority/storagehelper.h"
+
+#include <media_const.h>
+
+#include <QtCore/QStandardPaths>
+#include <QtCore/QDir>
+#include <QUrl>
+#include <QSize>
+
 #include <algorithm> // std::sort
 #include <chrono>
 #include <csignal>
@@ -29,23 +50,6 @@
 #include <string>
 #include <sstream>
 
-// Qt
-#include <QtCore/QStandardPaths>
-#include <QtCore/QDir>
-#include <QUrl>
-
-// Ring daemon
-#include <media_const.h>
-
-// LRC
-#include "api/call.h"
-#include "api/lrc.h"
-#include "callbackshandler.h"
-#include "dbus/callmanager.h"
-#include "dbus/configurationmanager.h"
-#include "dbus/videomanager.h"
-#include "authority/storagehelper.h"
-
 #if defined(Q_OS_UNIX) && !defined(__APPLE__)
 #include <xcb/xcb.h>
 #endif
@@ -53,6 +57,8 @@
 namespace lrc {
 
 using namespace api;
+using namespace api::video;
+using namespace lrc::video;
 
 class AVModelPimpl : public QObject
 {
@@ -66,8 +72,7 @@ public:
     AVModel& linked_;
 
     std::mutex renderers_mtx_;
-    std::map<QString, std::unique_ptr<video::Renderer>> renderers_;
-    bool useAVFrame_ = false;
+    std::map<QString, std::unique_ptr<Renderer>> renderers_;
     QString currentVideoCaptureDevice_ {};
 
 #ifndef ENABLE_LIBWRAP
@@ -87,12 +92,10 @@ public:
     /**
      * Add video::Renderer to renderers_ and start it
      * @param id
-     * @param settings
+     * @param size
      * @param shmPath
      */
-    void addRenderer(const QString& id,
-                     const video::Settings& settings,
-                     const QString& shmPath = {});
+    void addRenderer(const QString& id, const QSize& res, const QString& shmPath = {});
 
     /**
      * Remove renderer from renderers_
@@ -100,6 +103,10 @@ public:
      */
     void removeRenderer(const QString& id);
 
+    bool hasRenderer(const QString& id);
+    QSize getRendererSize(const QString& id);
+    Frame getRendererFrame(const QString& id);
+
 public Q_SLOTS:
     /**
      * Listen from CallbacksHandler when a renderer starts
@@ -115,11 +122,6 @@ public Q_SLOTS:
      * @param shmPath
      */
     void onDecodingStopped(const QString& id, const QString& shmPath);
-    /**
-     * Detect when the current frame is updated
-     * @param id
-     */
-    void slotFrameUpdated(const QString& id);
     /**
      * Detect when a video device is plugged or unplugged
      */
@@ -228,7 +230,7 @@ AVModel::setDefaultDevice(const QString& deviceId)
     VideoManager::instance().setDefaultDevice(deviceId);
 }
 
-video::Settings
+Settings
 AVModel::getDeviceSettings(const QString& deviceId) const
 {
     if (deviceId.isEmpty()) {
@@ -247,7 +249,7 @@ AVModel::getDeviceSettings(const QString& deviceId) const
     return result;
 }
 
-video::Capabilities
+Capabilities
 AVModel::getDeviceCapabilities(const QString& deviceId) const
 {
     // Channel x Resolution x Framerate
@@ -296,8 +298,7 @@ AVModel::setDeviceSettings(video::Settings& settings)
     // doing this during a call will cause re-invite, this is unwanted
     std::unique_lock<std::mutex> lk(pimpl_->renderers_mtx_);
     auto it = pimpl_->renderers_.find(video::PREVIEW_RENDERER_ID);
-    if (it != pimpl_->renderers_.end() && it->second && it->second->isRendering()
-        && pimpl_->renderers_.size() == 1) {
+    if (it != pimpl_->renderers_.end() && it->second && pimpl_->renderers_.size() == 1) {
         lk.unlock();
         stopPreview(video::PREVIEW_RENDERER_ID);
         startPreview(video::PREVIEW_RENDERER_ID);
@@ -513,16 +514,6 @@ AVModel::setRecordQuality(const int& rec) const
     ConfigurationManager::instance().setRecordQuality(rec);
 }
 
-void
-AVModel::useAVFrame(bool useAVFrame)
-{
-    pimpl_->useAVFrame_ = useAVFrame;
-    std::lock_guard<std::mutex> lk(pimpl_->renderers_mtx_);
-    for (auto it = pimpl_->renderers_.cbegin(); it != pimpl_->renderers_.cend(); ++it) {
-        it->second->useAVFrame(pimpl_->useAVFrame_);
-    }
-}
-
 QString
 AVModel::startPreview(const QString& resource)
 {
@@ -535,17 +526,6 @@ AVModel::stopPreview(const QString& resource)
     VideoManager::instance().closeVideoInput(resource);
 }
 
-const video::Renderer&
-AVModel::getRenderer(const QString& id) const
-{
-    std::lock_guard<std::mutex> lk(pimpl_->renderers_mtx_);
-    auto search = pimpl_->renderers_.find(id);
-    if (search == pimpl_->renderers_.end() || !search->second) {
-        throw std::out_of_range("Can't find renderer " + id.toStdString());
-    }
-    return *search->second;
-}
-
 #if defined(Q_OS_UNIX) && !defined(__APPLE__)
 static xcb_atom_t
 getAtom(xcb_connection_t* c, const std::string& atomName)
@@ -660,15 +640,37 @@ AVModel::clearCurrentVideoCaptureDevice()
 }
 
 void
-AVModel::addRenderer(const QString& id, const video::Settings& settings, const QString& shmPath)
+AVModel::addRenderer(const QString& id, const QSize& res, const QString& shmPath)
 {
-    pimpl_->addRenderer(id, settings, shmPath);
+    pimpl_->addRenderer(id, res, shmPath);
 }
 
-void
-AVModel::removeRenderer(const QString& id)
+bool
+AVModel::hasRenderer(const QString& id)
+{
+    return pimpl_->hasRenderer(id);
+}
+
+QSize
+AVModel::getRendererSize(const QString& id)
+{
+    return pimpl_->getRendererSize(id);
+}
+
+Frame
+AVModel::getRendererFrame(const QString& id)
+{
+    return pimpl_->getRendererFrame(id);
+}
+
+bool
+AVModel::useDirectRenderer() const
 {
-    pimpl_->removeRenderer(id);
+#ifdef ENABLE_LIBWRAP
+    return true;
+#else
+    return false;
+#endif
 }
 
 AVModelPimpl::AVModelPimpl(AVModel& linked, const CallbacksHandler& callbacksHandler)
@@ -752,9 +754,7 @@ AVModelPimpl::onDecodingStarted(const QString& id, const QString& shmPath, int w
 {
     if (id != "" && id != "local" && !id.contains("://")) // Else managed by callmodel
         return;
-    video::Settings settings;
-    settings.size = toQString(width) + "x" + toQString(height);
-    addRenderer(id, settings, shmPath);
+    addRenderer(id, QSize(width, height), shmPath);
 }
 
 void
@@ -765,13 +765,12 @@ AVModelPimpl::onDecodingStopped(const QString& id, const QString& shmPath)
 }
 
 #ifndef ENABLE_LIBWRAP
-
 void
 AVModelPimpl::stopCameraAndQuit(int)
 {
     if (SIZE_RENDERER == 1) {
         // This will stop the preview if needed (not in a call).
-        VideoManager::instance().closeVideoInput(video::PREVIEW_RENDERER_ID);
+        VideoManager::instance().closeVideoInput(PREVIEW_RENDERER_ID);
         // HACK: this sleep is just here to let the camera stop and
         // avoid immediate raise
         std::this_thread::sleep_for(std::chrono::milliseconds(50));
@@ -780,7 +779,6 @@ AVModelPimpl::stopCameraAndQuit(int)
 }
 
 #endif
-
 QString
 AVModelPimpl::getDevice(int type) const
 {
@@ -805,9 +803,9 @@ AVModelPimpl::getDevice(int type) const
             // Should not happen, but cannot retrieve current ringtone device
             return "";
         }
-        auto deviceIdx = currentDevicesIdx[type].toUInt();
+        auto deviceIdx = currentDevicesIdx[type].toInt();
         for (const auto& dev : devices) {
-            uint32_t idx;
+            int idx {-1};
             switch (type) {
             case 1: // INPUT
                 idx = ConfigurationManager::instance().getAudioInputDeviceIndex(dev);
@@ -831,35 +829,66 @@ AVModelPimpl::getDevice(int type) const
     return result;
 }
 
+static std::unique_ptr<Renderer>
+createRenderer(const QString& id, const QSize& res, const QString& shmPath = {})
+{
+#ifdef ENABLE_LIBWRAP
+    Q_UNUSED(shmPath)
+    return std::make_unique<DirectRenderer>(id, res);
+#else
+    return std::make_unique<ShmRenderer>(id, res, shmPath);
+#endif
+}
+
 void
-AVModelPimpl::addRenderer(const QString& id, const video::Settings& settings, const QString& shmPath)
+AVModelPimpl::addRenderer(const QString& id, const QSize& res, const QString& shmPath)
 {
     {
+        auto connectRenderer = [this](Renderer* renderer, const QString& id) {
+            connect(
+                renderer,
+                &Renderer::started,
+                this,
+                [this, id] { Q_EMIT linked_.rendererStarted(id); },
+                Qt::QueuedConnection);
+            connect(
+                renderer,
+                &Renderer::frameBufferRequested,
+                this,
+                [this, id](AVFrame* frame) { Q_EMIT linked_.frameBufferRequested(id, frame); },
+                Qt::DirectConnection);
+            connect(
+                renderer,
+                &Renderer::frameUpdated,
+                this,
+                [this, id] { Q_EMIT linked_.frameUpdated(id); },
+                Qt::DirectConnection);
+            connect(
+                renderer,
+                &Renderer::stopped,
+                this,
+                [this, id] { Q_EMIT linked_.rendererStopped(id); },
+                Qt::DirectConnection);
+        };
         std::lock_guard<std::mutex> lk(renderers_mtx_);
-        auto search = renderers_.find(id);
-        if (search == renderers_.end()) {
-            renderers_
-                .emplace(id, std::make_unique<video::Renderer>(id, settings, shmPath, useAVFrame_));
-            renderers_.at(id)->startRendering();
+        Renderer* renderer {nullptr};
+        auto it = renderers_.find(id);
+        if (it == renderers_.end()) {
+            renderers_.emplace(id, createRenderer(id, res, shmPath));
+            renderer = renderers_.at(id).get();
+            connectRenderer(renderer, id);
+            renderer->startRendering();
         } else {
-            if (search->second) {
-                search->second->update(settings.size, shmPath);
+            renderer = it->second.get();
+            if (renderer) {
+                renderer->update(res, shmPath);
             } else {
-                search->second.reset(new video::Renderer(id, settings, shmPath, useAVFrame_));
-                renderers_.at(id)->startRendering();
+                it->second.reset(createRenderer(id, res, shmPath).get());
+                renderer = it->second.get();
+                connectRenderer(renderer, id);
+                renderer->startRendering();
             }
         }
-        connect(
-            renderers_.at(id).get(),
-            &video::Renderer::started,
-            this,
-            [this](const QString& id) { emit linked_.rendererStarted(id); },
-            Qt::UniqueConnection);
-        connect(renderers_.at(id).get(),
-                &video::Renderer::frameUpdated,
-                this,
-                &AVModelPimpl::slotFrameUpdated,
-                Qt::UniqueConnection);
     }
 }
 
@@ -867,31 +896,41 @@ void
 AVModelPimpl::removeRenderer(const QString& id)
 {
     std::lock_guard<std::mutex> lk(renderers_mtx_);
-    auto search = renderers_.find(id);
-    if (search == renderers_.end()) {
+    auto it = renderers_.find(id);
+    if (it == renderers_.end()) {
         qWarning() << "Cannot remove renderer. " << id << "not found";
         return;
     }
-    disconnect(search->second.get(),
-               &video::Renderer::frameUpdated,
-               this,
-               &AVModelPimpl::slotFrameUpdated);
-    connect(
-        search->second.get(),
-        &video::Renderer::stopped,
-        this,
-        [this](const QString& id) {
-            renderers_.erase(id);
-            emit linked_.rendererStopped(id);
-        },
-        Qt::DirectConnection);
-    search->second.reset();
+    renderers_.erase(id);
 }
 
-void
-AVModelPimpl::slotFrameUpdated(const QString& id)
+bool
+AVModelPimpl::hasRenderer(const QString& id)
+{
+    std::lock_guard<std::mutex> lk(renderers_mtx_);
+    return renderers_.find(id) != renderers_.end();
+}
+
+QSize
+AVModelPimpl::getRendererSize(const QString& id)
 {
-    emit linked_.frameUpdated(id);
+    std::lock_guard<std::mutex> lk(renderers_mtx_);
+    auto it = renderers_.find(id);
+    if (it != renderers_.end()) {
+        return it->second->size();
+    }
+    return {};
+}
+
+Frame
+AVModelPimpl::getRendererFrame(const QString& id)
+{
+    std::lock_guard<std::mutex> lk(renderers_mtx_);
+    auto it = renderers_.find(id);
+    if (it != renderers_.end()) {
+        return it->second->currentFrame();
+    }
+    return {};
 }
 
 void
diff --git a/src/directrenderer.cpp b/src/directrenderer.cpp
index 0a3e4702a47f7345c6d5262900746aa8e32fc991..7c77298a08feca5dc72cdee38d6e9b2df34f9ee4 100644
--- a/src/directrenderer.cpp
+++ b/src/directrenderer.cpp
@@ -1,222 +1,130 @@
-/****************************************************************************
- *   Copyright (C) 2012-2022 Savoir-faire Linux Inc.                        *
- *   Author : Alexandre Lision <alexandre.lision@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             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#ifdef ENABLE_LIBWRAP
-
-#include "directrenderer.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QMutex>
-#include <QtCore/QThread>
-#include <QtCore/QTime>
-#include <QtCore/QTimer>
-
-#include <cstring>
-
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME 0
-#endif
-
-#include "private/videorenderer_p.h"
-#include "videomanager_interface.h"
-
-extern "C" {
-struct AVFrame;
-auto AVFrameDeleter = [](AVFrame* p) {
-};
-}
-
-namespace Video {
-class DirectRendererPrivate : public QObject
-{
-    Q_OBJECT
-public:
-    DirectRendererPrivate(Video::DirectRenderer* parent, bool useAVFrame);
-    DRing::SinkTarget::FrameBufferPtr requestFrameBuffer(std::size_t bytes);
-    void onNewFrame(DRing::SinkTarget::FrameBufferPtr buf);
-    void onNewAVFrame(std::unique_ptr<DRing::VideoFrame> frame);
-    void configureTarget(bool useAVFrame);
-
-    DRing::SinkTarget target;
-    DRing::AVSinkTarget av_target;
-    mutable QMutex directmutex;
-    mutable DRing::SinkTarget::FrameBufferPtr daemonFramePtr_;
-    std::unique_ptr<AVFrame, void (*)(AVFrame*)> avframe;
-
-private:
-    Video::DirectRenderer* q_ptr;
-};
-
-} // namespace Video
-
-Video::DirectRendererPrivate::DirectRendererPrivate(Video::DirectRenderer* parent, bool useAVFrame)
-    : QObject(parent)
-    , q_ptr(parent)
-    , avframe {nullptr, AVFrameDeleter}
-{
-    using namespace std::placeholders;
-    if (useAVFrame) {
-        av_target.push = std::bind(&Video::DirectRendererPrivate::onNewAVFrame, this, _1);
-        return;
-    }
-    target.pull = std::bind(&Video::DirectRendererPrivate::requestFrameBuffer, this, _1);
-    target.push = std::bind(&Video::DirectRendererPrivate::onNewFrame, this, _1);
-}
-
-/// Constructor
-Video::DirectRenderer::DirectRenderer(const QString& id, const QSize& res, bool useAVFrame)
-    : Renderer(id, res)
-    , d_ptr(std::make_unique<DirectRendererPrivate>(this, useAVFrame))
-{
-    setObjectName("Video::DirectRenderer:" + id);
-}
-
-/// Destructor
-Video::DirectRenderer::~DirectRenderer()
-{
-    QMutexLocker lk(mutex());
-    stopRendering();
-
-    d_ptr.reset();
-}
-
-void
-Video::DirectRenderer::startRendering()
-{
-    Video::Renderer::d_ptr->m_isRendering = true;
-    emit started();
-}
-void
-Video::DirectRenderer::stopRendering()
-{
-    Video::Renderer::d_ptr->m_isRendering = false;
-    emit stopped();
-}
-void
-Video::DirectRenderer::configureTarget(bool useAVFrame)
-{
-    d_ptr->configureTarget(useAVFrame);
-}
-
-DRing::SinkTarget::FrameBufferPtr
-Video::DirectRendererPrivate::requestFrameBuffer(std::size_t bytes)
-{
-    QMutexLocker lk(q_ptr->mutex());
-    if (not daemonFramePtr_)
-        daemonFramePtr_.reset(new DRing::FrameBuffer);
-    daemonFramePtr_->storage.resize(bytes);
-    daemonFramePtr_->ptr = daemonFramePtr_->storage.data();
-    daemonFramePtr_->ptrSize = bytes;
-    return std::move(daemonFramePtr_);
-}
-
-void
-Video::DirectRendererPrivate::configureTarget(bool useAVFrame)
-{
-    using namespace std::placeholders;
-    if (useAVFrame) {
-        target.pull = nullptr;
-        target.push = nullptr;
-        av_target.push = std::bind(&Video::DirectRendererPrivate::onNewAVFrame, this, _1);
-        return;
-    }
-    target.pull = std::bind(&Video::DirectRendererPrivate::requestFrameBuffer, this, _1);
-    target.push = std::bind(&Video::DirectRendererPrivate::onNewFrame, this, _1);
-    av_target.push = nullptr;
-}
-
-void
-Video::DirectRendererPrivate::onNewFrame(DRing::SinkTarget::FrameBufferPtr buf)
-{
-    if (not q_ptr->isRendering())
-        return;
-
-    {
-        QMutexLocker lk(q_ptr->mutex());
-        daemonFramePtr_ = std::move(buf);
-    }
-
-    emit q_ptr->frameUpdated();
-}
-
-void
-Video::DirectRendererPrivate::onNewAVFrame(std::unique_ptr<DRing::VideoFrame> frame)
-{
-    if (not q_ptr->isRendering())
-        return;
-    {
-        QMutexLocker lk(q_ptr->mutex());
-        avframe = std::move(frame->getFrame());
-    }
-    emit q_ptr->frameUpdated();
-}
-
-std::unique_ptr<AVFrame, void (*)(AVFrame*)>
-Video::DirectRenderer::currentAVFrame() const
-{
-    if (not isRendering())
-        return {nullptr, AVFrameDeleter};
-    QMutexLocker lock(mutex());
-    return std::move(d_ptr->avframe);
-}
-
-lrc::api::video::Frame
-Video::DirectRenderer::currentFrame() const
-{
-    if (not isRendering())
-        return {};
-
-    QMutexLocker lock(mutex());
-    if (not d_ptr->daemonFramePtr_)
-        return {};
-
-    lrc::api::video::Frame frame;
-    frame.storage = std::move(d_ptr->daemonFramePtr_->storage);
-    frame.ptr = frame.storage.data();
-    frame.size = frame.storage.size();
-    frame.height = d_ptr->daemonFramePtr_->height;
-    frame.width = d_ptr->daemonFramePtr_->width;
-
-    return std::move(frame);
-}
-
-const DRing::SinkTarget&
-Video::DirectRenderer::target() const
-{
-    return d_ptr->target;
-}
-
-const DRing::AVSinkTarget&
-Video::DirectRenderer::avTarget() const
-{
-    return d_ptr->av_target;
-}
-
-Video::Renderer::ColorSpace
-Video::DirectRenderer::colorSpace() const
-{
-#ifdef Q_OS_DARWIN
-    return Video::Renderer::ColorSpace::RGBA;
-#else
-    return Video::Renderer::ColorSpace::BGRA;
-#endif
-}
-
-#include <directrenderer.moc>
-
-#endif
+/*
+ *  Copyright (C) 2012-2022 Savoir-faire Linux Inc.
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *  Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ * 
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "directrenderer.h"
+
+#include "dbus/videomanager.h"
+#include "videomanager_interface.h"
+
+#include <QMutex>
+
+namespace lrc {
+namespace video {
+
+using namespace lrc::api::video;
+
+struct DirectRenderer::Impl : public QObject
+{
+    Q_OBJECT
+public:
+    Impl(DirectRenderer* parent)
+        : QObject(nullptr)
+        , parent_(parent)
+    {
+        configureTarget();
+        VideoManager::instance().registerSinkTarget(parent_->id(), target);
+    };
+    ~Impl()
+    {
+        parent_->stopRendering();
+        VideoManager::instance().registerSinkTarget(parent_->id(), {});
+    }
+
+    // sink target callbacks
+    void configureTarget()
+    {
+        using namespace std::placeholders;
+        target.pull = std::bind(&Impl::pullCallback, this, _1);
+        target.push = std::bind(&Impl::pushCallback, this, _1);
+    };
+
+    DRing::SinkTarget::FrameBufferPtr pullCallback(std::size_t bytes)
+    {
+        QMutexLocker lk(&mutex);
+        if (!frameBufferPtr) {
+            frameBufferPtr.reset(new DRing::FrameBuffer);
+            frameBufferPtr->avframe.reset(av_frame_alloc());
+        }
+
+        // A response to this signal should be used to provide client
+        // allocated buffer specs via the AVFrame structure.
+        // Important: Subscription to this signal MUST be synchronous(Qt::DirectConnection).
+        Q_EMIT parent_->frameBufferRequested(frameBufferPtr->avframe.get());
+
+        return std::move(frameBufferPtr);
+    };
+
+    void pushCallback(DRing::SinkTarget::FrameBufferPtr buf)
+    {
+        {
+            QMutexLocker lk(&mutex);
+            frameBufferPtr = std::move(buf);
+        }
+
+        Q_EMIT parent_->frameUpdated();
+    };
+
+private:
+    DirectRenderer* parent_;
+
+public:
+    DRing::SinkTarget target;
+    QMutex mutex;
+    DRing::SinkTarget::FrameBufferPtr frameBufferPtr;
+};
+
+DirectRenderer::DirectRenderer(const QString& id, const QSize& res)
+    : Renderer(id, res)
+    , pimpl_(std::make_unique<DirectRenderer::Impl>(this))
+{}
+
+DirectRenderer::~DirectRenderer() {}
+
+void
+DirectRenderer::startRendering()
+{
+    Q_EMIT started();
+}
+
+void
+DirectRenderer::stopRendering()
+{
+    Q_EMIT stopped();
+}
+
+void
+DirectRenderer::update(const QSize& res, const QString&)
+{
+    Renderer::update(res);
+
+    VideoManager::instance().registerSinkTarget(id(), pimpl_->target);
+}
+
+Frame
+DirectRenderer::currentFrame() const
+{
+    return {};
+}
+
+} // namespace video
+} // namespace lrc
+
+#include "moc_directrenderer.cpp"
+#include "directrenderer.moc"
diff --git a/src/directrenderer.h b/src/directrenderer.h
index 54722d1bcfdd92fde70d5d1921ca5fd41b5c520a..dfcd026590123c9d23b717d4f7c27d5270ee4330 100644
--- a/src/directrenderer.h
+++ b/src/directrenderer.h
@@ -1,67 +1,49 @@
-/****************************************************************************
- *    Copyright (C) 2012-2022 Savoir-faire Linux Inc.                       *
- *   Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com>      *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#pragma once
+/*
+ *  Copyright (C) 2012-2022 Savoir-faire Linux Inc.
+ *  Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *  Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 
-#ifdef ENABLE_LIBWRAP
+#pragma once
 
-// Base
-#include <QtCore/QObject>
+#include "renderer.h"
 #include "typedefs.h"
-#include "video/renderer.h"
-#include "videomanager_interface.h"
-
-// Qt
-class QMutex;
-class QTimer;
-class QThread;
 
-namespace Video {
-class DirectRendererPrivate;
+namespace lrc {
+namespace video {
 
-/// Manage shared memory and convert it to QByteArray
-class LIB_EXPORT DirectRenderer final : public Renderer
+class DirectRenderer final : public Renderer
 {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
     Q_OBJECT
-#pragma GCC diagnostic pop
-
 public:
-    // Constructor
-    DirectRenderer(const QString& id, const QSize& res, bool useAVFrame);
-    virtual ~DirectRenderer();
+    DirectRenderer(const QString& id, const QSize& res);
+    ~DirectRenderer();
 
-    // Getter
-    const DRing::SinkTarget& target() const;
-    const DRing::AVSinkTarget& avTarget() const;
-    virtual ColorSpace colorSpace() const override;
-    virtual lrc::api::video::Frame currentFrame() const override;
-    virtual std::unique_ptr<AVFrame, void (*)(AVFrame*)> currentAVFrame() const override;
-    void configureTarget(bool useAVFrame);
+    // Renderer interface.
+    void update(const QSize& res, const QString& shmPath) override;
+    lrc::api::video::Frame currentFrame() const override;
 
 public Q_SLOTS:
-    virtual void startRendering() override;
-    virtual void stopRendering() override;
+    void startRendering() override;
+    void stopRendering() override;
 
 private:
-    std::unique_ptr<DirectRendererPrivate> d_ptr;
+    struct Impl;
+    std::unique_ptr<Impl> pimpl_;
 };
 
-} // namespace Video
-
-#endif
+} // namespace video
+} // namespace lrc
diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp
index 4e0188ef9d39dea82c1d6c28423caf747e6eac78..3bd8cb3ee1b4af421c49110265169500c647b817 100644
--- a/src/newcallmodel.cpp
+++ b/src/newcallmodel.cpp
@@ -33,7 +33,7 @@
 #include "dbus/callmanager.h"
 #include "dbus/videomanager.h"
 #include "vcard.h"
-#include "video/renderer.h"
+#include "renderer.h"
 #include "typedefs.h"
 #include "uri.h"
 
@@ -45,6 +45,7 @@
 #include <QObject>
 #include <QString>
 #include <QUrl>
+#include <QSize>
 
 // std
 #include <chrono>
@@ -118,6 +119,7 @@ using namespace api;
 
 class NewCallModelPimpl : public QObject
 {
+    Q_OBJECT
 public:
     NewCallModelPimpl(const NewCallModel& linked,
                       Lrc& lrc,
@@ -773,7 +775,7 @@ NewCallModel::getPendingConferencees()
     return pimpl_->pendingConferencees_;
 }
 
-video::RenderedDevice
+api::video::RenderedDevice
 NewCallModel::getCurrentRenderedDevice(const QString& call_id) const
 {
     video::RenderedDevice result;
@@ -1591,16 +1593,18 @@ NewCallModelPimpl::remoteRecordingChanged(const QString& callId,
 }
 
 void
-NewCallModelPimpl::onDecodingStarted(const QString& id, const QString& shmPath, int width, int height)
+NewCallModelPimpl::onDecodingStarted(const QString& id,
+                                     const QString& shmPath,
+                                     int width,
+                                     int height)
 {
     auto it = calls.find(id);
     if (it == calls.end())
         return;
-    video::Settings settings;
-    settings.size = toQString(width) + "x" + toQString(height);
-    lrc.getAVModel().addRenderer(id, settings, shmPath);
+    lrc.getAVModel().addRenderer(id, QSize(width, height), shmPath);
 }
 
 } // namespace lrc
 
 #include "api/moc_newcallmodel.cpp"
+#include "newcallmodel.moc"
diff --git a/src/newvideo.cpp b/src/newvideo.cpp
deleted file mode 100644
index b48fde0638ba82d624c2767cfeff70e7334e1fde..0000000000000000000000000000000000000000
--- a/src/newvideo.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/****************************************************************************
- *    Copyright (C) 2018-2022 Savoir-faire Linux Inc.                       *
- *   Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>           *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-
-#include "api/newvideo.h"
-
-#include "dbus/videomanager.h"
-#ifdef ENABLE_LIBWRAP
-#include "directrenderer.h"
-#else
-#include "shmrenderer.h"
-#endif
-
-#include <QSize>
-
-#include <mutex>
-
-namespace lrc {
-
-using namespace api::video;
-
-class RendererPimpl : public QObject
-{
-public:
-    RendererPimpl(Renderer& linked,
-                  const QString& id,
-                  Settings videoSettings,
-                  const QString& shmPath,
-                  const bool useAVFrame);
-    ~RendererPimpl();
-
-    Renderer& linked_;
-
-    QString id_;
-    Settings videoSettings_;
-    QThread thread_;
-    bool usingAVFrame_;
-
-    /**
-     * Convert a string (WxH) to a QSize
-     * @param res the string to convert
-     * @return the QSize object
-     */
-    static QSize stringToQSize(const QString& res);
-
-#ifdef ENABLE_LIBWRAP
-    std::unique_ptr<Video::DirectRenderer> renderer;
-#else
-    std::unique_ptr<Video::ShmRenderer> renderer;
-#endif
-
-public Q_SLOTS:
-    /**
-     * Detect when the current frame is updated
-     */
-    void slotFrameUpdated();
-};
-
-namespace api {
-
-namespace video {
-
-Renderer::Renderer(const QString& id,
-                   Settings videoSettings,
-                   const QString& shmPath,
-                   const bool useAVFrame)
-    : pimpl_(std::make_unique<RendererPimpl>(*this, id, videoSettings, shmPath, useAVFrame))
-{}
-
-Renderer::~Renderer()
-{
-#ifdef ENABLE_LIBWRAP
-    if (pimpl_->usingAVFrame_) {
-        VideoManager::instance().registerAVSinkTarget(pimpl_->id_, {});
-    } else {
-        VideoManager::instance().registerSinkTarget(pimpl_->id_, {});
-    }
-#else
-    VideoManager::instance().startShmSink(pimpl_->id_, false);
-#endif // ENABLE_LIBWRAP
-
-    pimpl_.reset();
-}
-
-void
-Renderer::update(const QString& res, const QString& shmPath)
-{
-    if (!pimpl_->thread_.isRunning())
-        pimpl_->thread_.start();
-
-    // res = "WIDTHxHEIGHT"
-    QSize size = RendererPimpl::stringToQSize(res);
-    pimpl_->renderer->setSize(size);
-
-#ifdef ENABLE_LIBWRAP
-    Q_UNUSED(shmPath)
-    if (pimpl_->usingAVFrame_) {
-        VideoManager::instance().registerAVSinkTarget(pimpl_->id_, pimpl_->renderer->avTarget());
-    } else {
-        VideoManager::instance().registerSinkTarget(pimpl_->id_, pimpl_->renderer->target());
-    }
-#else // ENABLE_LIBWRAP
-    pimpl_->renderer->setShmPath(shmPath);
-    VideoManager::instance().startShmSink(pimpl_->id_, true);
-#endif
-}
-
-bool
-Renderer::isRendering() const
-{
-    if (pimpl_->renderer)
-        return pimpl_->renderer->isRendering();
-    return false;
-}
-
-void
-Renderer::useAVFrame(bool useAVFrame)
-{
-    pimpl_->usingAVFrame_ = useAVFrame;
-#ifdef ENABLE_LIBWRAP
-    pimpl_->renderer->configureTarget(useAVFrame);
-#endif
-}
-
-bool
-Renderer::useDirectRenderer() const
-{
-#ifdef ENABLE_LIBWRAP
-    return true;
-#else
-    return false;
-#endif
-}
-
-QString
-Renderer::getId() const
-{
-    return pimpl_->id_;
-}
-
-Frame
-Renderer::currentFrame() const
-{
-    // TODO(sblin) remove Video::Frame when deleting old models.
-    auto frame = pimpl_->renderer->currentFrame();
-    Frame result;
-    result.ptr = frame.ptr;
-    result.size = frame.size;
-    result.storage = frame.storage;
-    result.height = frame.height;
-    result.width = frame.width;
-    return result;
-}
-
-#if defined(ENABLE_LIBWRAP)
-std::unique_ptr<AVFrame, void (*)(AVFrame*)>
-Renderer::currentAVFrame() const
-{
-    return pimpl_->renderer->currentAVFrame();
-}
-#endif
-
-QSize
-Renderer::size() const
-{
-    return pimpl_->renderer->size();
-}
-
-} // namespace video
-} // namespace api
-
-RendererPimpl::RendererPimpl(Renderer& linked,
-                             const QString& id,
-                             Settings videoSettings,
-                             const QString& shmPath,
-                             bool useAVFrame)
-    : linked_(linked)
-    , id_(id)
-    , videoSettings_(videoSettings)
-    , usingAVFrame_(useAVFrame)
-{
-    QSize size = stringToQSize(videoSettings.size);
-#ifdef ENABLE_LIBWRAP
-    Q_UNUSED(shmPath)
-    renderer = std::make_unique<Video::DirectRenderer>(id, size, usingAVFrame_);
-#else // ENABLE_LIBWRAP
-    renderer = std::make_unique<Video::ShmRenderer>(id, shmPath, size);
-#endif
-    renderer->moveToThread(&thread_);
-
-    connect(&thread_, &QThread::finished, [this] { renderer.reset(); });
-
-    connect(&linked,
-            &Renderer::startRendering,
-            renderer.get(),
-            &Video::Renderer::startRendering,
-            Qt::QueuedConnection);
-
-    connect(renderer.get(), &Video::Renderer::frameUpdated, [this] {
-        emit linked_.frameUpdated(id_);
-    });
-
-    connect(
-        renderer.get(),
-        &Video::Renderer::started,
-        this,
-        [this] { emit linked_.started(id_); },
-        Qt::DirectConnection);
-    connect(
-        renderer.get(),
-        &Video::Renderer::stopped,
-        this,
-        [this] { emit linked_.stopped(id_); },
-        Qt::DirectConnection);
-
-#ifdef ENABLE_LIBWRAP
-    if (usingAVFrame_) {
-        VideoManager::instance().registerAVSinkTarget(id_, renderer->avTarget());
-    } else {
-        VideoManager::instance().registerSinkTarget(id_, renderer->target());
-    }
-#else
-    VideoManager::instance().startShmSink(id_, true);
-#endif
-
-    thread_.start();
-}
-
-RendererPimpl::~RendererPimpl()
-{
-    thread_.quit();
-    thread_.wait();
-}
-
-QSize
-RendererPimpl::stringToQSize(const QString& res)
-{
-    QString sizeStr = res;
-    auto sizeSplited = sizeStr.split('x');
-    if (sizeSplited.size() != 2)
-        return {};
-    auto width = sizeSplited.at(0).toInt();
-    auto height = sizeSplited.at(1).toInt();
-    return QSize(width, height);
-}
-
-} // end of namespace lrc
-
-#include "api/moc_newvideo.cpp"
diff --git a/src/private/videorenderer_p.h b/src/private/videorenderer_p.h
deleted file mode 100644
index c247d4f16b5c87252a6a0bbba43b58496c7ce000..0000000000000000000000000000000000000000
--- a/src/private/videorenderer_p.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
- *    Copyright (C) 2013-2022 Savoir-faire Linux Inc.                       *
- *   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             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#pragma once
-
-// Qt
-#include <QtCore/QObject>
-#include <QtCore/QSize>
-
-#include "api/newvideo.h"
-
-// Std
-#include <atomic>
-#include <memory>
-
-class QMutex;
-
-namespace Video {
-
-class Renderer;
-
-class RendererPrivate final : public QObject
-{
-    Q_OBJECT
-public:
-    RendererPrivate(Video::Renderer* parent);
-
-    // Attributes
-    std::atomic_bool m_isRendering;
-    QMutex* m_pMutex;
-    QString m_Id;
-    QSize m_pSize;
-    std::shared_ptr<lrc::api::video::Frame> m_pFrame; // frame given by daemon for direct rendering
-private:
-    Video::Renderer* q_ptr;
-};
-
-} // namespace Video
diff --git a/src/renderer.cpp b/src/renderer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a2065fd133cf170b092b78ad6e82b0f59f191fe
--- /dev/null
+++ b/src/renderer.cpp
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2018-2022 Savoir-faire Linux Inc.
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "renderer.h"
+
+#include <QSize>
+#include <QMutex>
+
+namespace lrc {
+namespace video {
+
+using namespace lrc::api::video;
+
+Renderer::Renderer(const QString& id, const QSize& res)
+    : id_(id)
+    , size_(res)
+    , QObject(nullptr)
+{}
+
+Renderer::~Renderer() {}
+
+QString
+Renderer::id() const
+{
+    return id_;
+}
+
+QSize
+Renderer::size() const
+{
+    return size_;
+}
+
+void
+Renderer::update(const QSize& size, const QString&)
+{
+    size_ = size;
+}
+
+} // namespace video
+} // namespace lrc
diff --git a/src/renderer.h b/src/renderer.h
new file mode 100644
index 0000000000000000000000000000000000000000..9e91bc29fdf01cd7f266be8311fd3a830d1d3349
--- /dev/null
+++ b/src/renderer.h
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (C) 2018-2022 Savoir-faire Linux Inc.
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "api/video.h"
+#include "typedefs.h"
+
+#include <QObject>
+#include <QSize>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace lrc {
+namespace video {
+
+class Renderer : public QObject
+{
+    Q_OBJECT
+public:
+    Renderer(const QString& id, const QSize& res);
+    virtual ~Renderer();
+
+    /**
+     * @return renderer's id
+     */
+    QString id() const;
+
+    /**
+     * @return current renderer dimensions
+     */
+    QSize size() const;
+
+    /**
+     * Update size and shmPath of a renderer
+     * @param size new renderer dimensions
+     * @param shmPath new shmPath
+     */
+    virtual void update(const QSize& size, const QString& shmPath = {});
+
+    /**
+     * @return current rendered frame
+     */
+    virtual lrc::api::video::Frame currentFrame() const = 0;
+
+public Q_SLOTS:
+    virtual void startRendering() = 0;
+    virtual void stopRendering() = 0;
+
+Q_SIGNALS:
+    void frameUpdated();
+    void stopped();
+    void started();
+    void frameBufferRequested(AVFrame* avFrame);
+
+private:
+    QString id_;
+    QSize size_;
+};
+
+} // namespace video
+} // namespace lrc
diff --git a/src/shmrenderer.cpp b/src/shmrenderer.cpp
index 2a007722f17ab006011c5e7394471ae8d09a1fb0..ab7f9e175a40cdec43116edd9f3268259a7a3587 100644
--- a/src/shmrenderer.cpp
+++ b/src/shmrenderer.cpp
@@ -1,28 +1,30 @@
-/****************************************************************************
- *    Copyright (C) 2012-2022 Savoir-faire Linux Inc.                       *
- *   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             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#ifndef ENABLE_LIBWRAP
+/*
+ *  Copyright (C) 2012-2022 Savoir-faire Linux Inc.
+ *  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
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 
 #include "shmrenderer.h"
 
-#include <QtCore/QDebug>
-#include <QtCore/QMutex>
-#include <QtCore/QThread>
+#include "dbus/videomanager.h"
+#include "videomanager_interface.h"
+
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
 
 #include <sys/ipc.h>
 #include <sys/sem.h>
@@ -37,10 +39,15 @@
 #define CLOCK_REALTIME 0
 #endif
 
-#include <QtCore/QTimer>
+#include <QTimer>
+
 #include <chrono>
 
-#include "private/videorenderer_p.h"
+namespace lrc {
+
+using namespace api::video;
+
+namespace video {
 
 // Uncomment following line to output in console the FPS value
 //#define DEBUG_FPS
@@ -69,330 +76,274 @@ struct SHMHeader
 #pragma GCC diagnostic pop
 };
 
-namespace Video {
-
-class ShmRendererPrivate final : public QObject
+struct ShmRenderer::Impl final : public QObject
 {
     Q_OBJECT
-
 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;
-    QTimer* m_pTimer;
+    Impl(ShmRenderer* parent)
+        : QObject(nullptr)
+        , parent_(parent)
+        , fd(-1)
+        , shmArea((SHMHeader*) MAP_FAILED)
+        , shmAreaLen(0)
+        , frameGen(0)
+        , fpsC(0)
+        , fps(0)
+        , timer(new QTimer(this))
+#ifdef DEBUG_FPS
+        , frameCount(0)
+        , lastFrameDebug(std::chrono::system_clock::now())
+#endif
+    {
+        timer->setInterval(33);
+        connect(timer, &QTimer::timeout, [this]() { Q_EMIT parent_->frameUpdated(); });
+        VideoManager::instance().startShmSink(parent_->id(), true);
+
+        parent_->moveToThread(&thread);
+        connect(&thread, &QThread::finished, [this] { parent_->stopRendering(); });
+        thread.start();
+    };
+    ~Impl()
+    {
+        thread.quit();
+        thread.wait();
+    }
 
     // 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();
+    // Lock the memory while the copy is being made
+    bool shmLock() { return ::sem_wait(&shmArea->mutex) >= 0; };
 
-private:
-    Video::ShmRenderer* q_ptr;
-};
+    // Remove the lock, allow a new frame to be drawn
+    void shmUnlock() { ::sem_post(&shmArea->mutex); };
 
-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)
-    , m_pTimer(nullptr)
-#ifdef DEBUG_FPS
-    , m_frameCount(0)
-    , m_lastFrameDebug(std::chrono::system_clock::now())
-#endif
-{}
+    // Wait for new frame data from shared memory and save pointer.
+    bool getNewFrame(bool wait)
+    {
+        if (!shmLock())
+            return false;
 
-/// Constructor
-ShmRenderer::ShmRenderer(const QString& id, const QString& shmPath, const QSize& res)
-    : Renderer(id, res)
-    , d_ptr(std::make_unique<ShmRendererPrivate>(this))
-{
-    d_ptr->m_ShmPath = shmPath;
-    setObjectName("Video::Renderer:" + id);
-}
+        if (frameGen == shmArea->frameGen) {
+            shmUnlock();
 
-/// Destructor
-ShmRenderer::~ShmRenderer()
-{
-    stopShm();
-}
+            if (not wait)
+                return false;
 
-/// Wait new frame data from shared memory and save pointer
-bool
-ShmRendererPrivate::getNewFrame(bool wait)
-{
-    if (!shmLock())
-        return false;
+            // wait for a new frame, max 33ms
+            static const struct timespec timeout = {0, 33000000};
+            if (::sem_timedwait(&shmArea->frameGenMutex, &timeout) < 0)
+                return false;
 
-    if (m_FrameGen == m_pShmArea->frameGen) {
-        shmUnlock();
+            if (!shmLock())
+                return false;
+        }
 
-        if (not wait)
+        // valid frame to render (daemon may have stopped)?
+        if (!shmArea->frameSize) {
+            shmUnlock();
             return false;
+        }
 
-        // wait for a new frame, max 33ms
-        static const struct timespec timeout = {0, 33000000};
-        if (::sem_timedwait(&m_pShmArea->frameGenMutex, &timeout) < 0)
+        // map frame data
+        if (!remapShm()) {
+            qDebug() << "Could not resize shared memory";
             return false;
+        }
 
-        if (!shmLock())
-            return false;
-    }
+        if (not frame)
+            frame.reset(new lrc::api::video::Frame);
+        frame->ptr = shmArea->data + shmArea->readOffset;
+        frame->size = shmArea->frameSize;
+        frameGen = shmArea->frameGen;
 
-    // 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";
-        return false;
-    }
+        ++fpsC;
 
-    auto& frame_ptr = q_ptr->Video::Renderer::d_ptr->m_pFrame;
-    if (not frame_ptr)
-        frame_ptr.reset(new lrc::api::video::Frame);
-    frame_ptr->storage.clear();
-    frame_ptr->ptr = m_pShmArea->data + m_pShmArea->readOffset;
-    frame_ptr->size = m_pShmArea->frameSize;
-    m_FrameGen = m_pShmArea->frameGen;
-
-    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 = (int) (m_fpsC / seconds.count());
-        m_fpsC = 0;
-        m_lastFrameDebug = currentTime;
+        // Compute the FPS shown to the client
+        auto currentTime = std::chrono::system_clock::now();
+        const std::chrono::duration<double> seconds = currentTime - lastFrameDebug;
+        if (seconds.count() >= FPS_RATE_SEC) {
+            fps = (int) (fpsC / seconds.count());
+            fpsC = 0;
+            lastFrameDebug = currentTime;
 #ifdef DEBUG_FPS
-        qDebug() << this << ": FPS " << m_fps;
+            qDebug() << this << ": FPS " << fps;
 #endif
-    }
+        }
 
-    return true;
-}
+        return true;
+    };
 
-/// Remap the shared memory
-/// Shared memory in unlocked state if returns false (resize failed).
-bool
-ShmRendererPrivate::remapShm()
-{
-    // This loop handles case where daemon resize shared memory
-    // during time we unlock it for remapping.
-    while (m_ShmAreaLen != m_pShmArea->mapSize) {
-        auto mapSize = m_pShmArea->mapSize;
-        shmUnlock();
+    // Remap the shared memory.
+    // Shared memory is in an unlocked state if returns false (resize failed).
+    bool remapShm()
+    {
+        // This loop handles case where daemon resize shared memory
+        // during time we unlock it for remapping.
+        while (shmAreaLen != shmArea->mapSize) {
+            auto mapSize = shmArea->mapSize;
+            shmUnlock();
 
-        if (::munmap(m_pShmArea, m_ShmAreaLen)) {
-            qDebug() << "Could not unmap shared area: " << strerror(errno);
-            return false;
-        }
+            if (::munmap(shmArea, 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);
+            shmArea
+                = (SHMHeader*) ::mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
-        if (m_pShmArea == MAP_FAILED) {
-            qDebug() << "Could not remap shared area: " << strerror(errno);
-            return false;
+            if (shmArea == MAP_FAILED) {
+                qDebug() << "Could not remap shared area: " << strerror(errno);
+                return false;
+            }
+
+            if (!shmLock())
+                return false;
+
+            shmAreaLen = mapSize;
         }
 
-        if (!shmLock())
-            return false;
+        return true;
+    };
 
-        m_ShmAreaLen = mapSize;
-    }
+private:
+    ShmRenderer* parent_;
 
-    return true;
+public:
+    QString path;
+    int fd;
+    SHMHeader* shmArea;
+    unsigned shmAreaLen;
+    uint frameGen;
+
+    int fpsC;
+    int fps;
+    std::chrono::time_point<std::chrono::system_clock> lastFrameDebug;
+
+    QTimer* timer;
+    QMutex mutex;
+    QThread thread;
+    std::shared_ptr<lrc::api::video::Frame> frame;
+};
+
+ShmRenderer::ShmRenderer(const QString& id, const QSize& res, const QString& shmPath)
+    : Renderer(id, res)
+    , pimpl_(std::make_unique<ShmRenderer::Impl>(this))
+{
+    pimpl_->path = shmPath;
+}
+
+ShmRenderer::~ShmRenderer()
+{
+    VideoManager::instance().startShmSink(id(), false);
+    stopShm();
+}
+
+void
+ShmRenderer::update(const QSize& res, const QString& shmPath)
+{
+    Renderer::update(res);
+
+    if (!pimpl_->thread.isRunning())
+        pimpl_->thread.start();
+
+    pimpl_->path = shmPath;
+    VideoManager::instance().startShmSink(id(), true);
+}
+
+Frame
+ShmRenderer::currentFrame() const
+{
+    QMutexLocker lk {&pimpl_->mutex};
+    if (pimpl_->getNewFrame(false)) {
+        if (auto frame_ptr = pimpl_->frame)
+            return std::move(*frame_ptr);
+    }
+    return {};
 }
 
-/// Connect to the shared memory
 bool
 ShmRenderer::startShm()
 {
-    if (d_ptr->m_fd != -1) {
+    if (pimpl_->fd != -1) {
         qWarning() << "fd must be -1";
         return false;
     }
 
-    d_ptr->m_fd = ::shm_open(d_ptr->m_ShmPath.toLatin1(), O_RDWR, 0);
+    pimpl_->fd = ::shm_open(pimpl_->path.toLatin1(), O_RDWR, 0);
 
-    if (d_ptr->m_fd < 0) {
-        qWarning() << "could not open shm area" << d_ptr->m_ShmPath
+    if (pimpl_->fd < 0) {
+        qWarning() << "could not open shm area" << pimpl_->path
                    << ", shm_open failed:" << strerror(errno);
         return false;
     }
 
     // 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);
+    pimpl_->shmArea
+        = (SHMHeader*) ::mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, pimpl_->fd, 0);
 
-    if (d_ptr->m_pShmArea == MAP_FAILED) {
+    if (pimpl_->shmArea == MAP_FAILED) {
         qWarning() << "Could not remap shared area";
         return false;
     }
 
-    d_ptr->m_ShmAreaLen = mapSize;
+    pimpl_->shmAreaLen = mapSize;
     return true;
 }
 
-/// Disconnect from the shared memory
 void
 ShmRenderer::stopShm()
 {
-    if (d_ptr->m_fd < 0)
+    if (pimpl_->fd < 0)
         return;
 
-    Video::Renderer::d_ptr->m_isRendering = false;
-
-    if (d_ptr->m_pTimer) {
-        d_ptr->m_pTimer->stop();
-        d_ptr->m_pTimer = nullptr;
-    }
+    pimpl_->timer->stop();
 
     // Emit the signal before closing the file, this lower the risk of invalid
     // memory access
-    emit stopped();
+    Q_EMIT stopped();
 
     {
-        QMutexLocker lk {mutex()};
+        QMutexLocker lk(&pimpl_->mutex);
         // reset the frame so it doesn't point to an old value
-        Video::Renderer::d_ptr->m_pFrame.reset();
+        pimpl_->frame.reset();
     }
 
-    ::close(d_ptr->m_fd);
-    d_ptr->m_fd = -1;
+    ::close(pimpl_->fd);
+    pimpl_->fd = -1;
 
-    if (d_ptr->m_pShmArea == MAP_FAILED)
+    if (pimpl_->shmArea == MAP_FAILED)
         return;
 
-    ::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
-ShmRendererPrivate::shmLock()
-{
-    return ::sem_wait(&m_pShmArea->mutex) >= 0;
-}
-
-/// Remove the lock, allow a new frame to be drawn
-void
-ShmRendererPrivate::shmUnlock()
-{
-    ::sem_post(&m_pShmArea->mutex);
+    ::munmap(pimpl_->shmArea, pimpl_->shmAreaLen);
+    pimpl_->shmAreaLen = 0;
+    pimpl_->shmArea = (SHMHeader*) MAP_FAILED;
 }
 
-/*****************************************************************************
- *                                                                           *
- *                                   Slots                                   *
- *                                                                           *
- ****************************************************************************/
-
-/// Start the rendering loop
 void
 ShmRenderer::startRendering()
 {
-    QMutexLocker locker {mutex()};
+    QMutexLocker lk(&pimpl_->mutex);
 
-    if (!startShm() || Video::Renderer::d_ptr->m_isRendering)
+    if (!startShm())
         return;
 
-    Video::Renderer::d_ptr->m_isRendering = true;
-
-    if (!d_ptr->m_pTimer) {
-        d_ptr->m_pTimer = new QTimer(this);
-        d_ptr->m_pTimer->setInterval(33);
-        connect(d_ptr->m_pTimer, &QTimer::timeout, [this]() { emit this->frameUpdated(); });
-    }
-    // FIXME This is a temporary hack as frameUpdated() is no longer emitted
-    d_ptr->m_pTimer->start();
+    pimpl_->timer->start();
 
-    emit started();
+    Q_EMIT started();
 }
 
-/// Done on destroy instead
+// Done on destroy instead
 void
 ShmRenderer::stopRendering()
 {}
 
-/*****************************************************************************
- *                                                                           *
- *                                 Getters                                   *
- *                                                                           *
- ****************************************************************************/
+} // namespace video
+} // namespace lrc
 
-/// Get the current frame rate of this renderer
-int
-ShmRenderer::fps() const
-{
-    return d_ptr->m_Fps;
-}
-
-/// Get frame data pointer from shared memory
-lrc::api::video::Frame
-ShmRenderer::currentFrame() const
-{
-    if (not isRendering())
-        return {};
-
-    QMutexLocker lk {mutex()};
-    if (d_ptr->getNewFrame(false)) {
-        if (auto frame_ptr = Video::Renderer::d_ptr->m_pFrame)
-            return std::move(*frame_ptr);
-    }
-    return {};
-}
-
-Video::Renderer::ColorSpace
-ShmRenderer::colorSpace() const
-{
-    return Video::Renderer::ColorSpace::BGRA;
-}
-
-/*****************************************************************************
- *                                                                           *
- *                                 Setters                                   *
- *                                                                           *
- ****************************************************************************/
-
-void
-ShmRenderer::setShmPath(const QString& path)
-{
-    d_ptr->m_ShmPath = path;
-}
-
-} // namespace Video
-
-#include <shmrenderer.moc>
-
-#endif
+#include "moc_shmrenderer.cpp"
+#include "shmrenderer.moc"
diff --git a/src/shmrenderer.h b/src/shmrenderer.h
index 56445b367420b096d48f6f5515f988e03e77d201..7880432a1c5829ee217ea877b1691e15f2bdf109 100644
--- a/src/shmrenderer.h
+++ b/src/shmrenderer.h
@@ -1,72 +1,51 @@
-/****************************************************************************
- *    Copyright (C) 2012-2022 Savoir-faire Linux Inc.                       *
- *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#pragma once
+/*
+ *  Copyright (C) 2012-2022 Savoir-faire Linux Inc.
+ *  Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
 
-#ifndef ENABLE_LIBWRAP
+#pragma once
 
-// Base
-#include "video/renderer.h"
+#include "renderer.h"
 #include "typedefs.h"
-#include "api/newvideo.h"
-
-// Qt
-class QMutex;
-
-// Private
-struct SHMHeader;
-struct AVFrame;
 
-namespace Video {
-class ShmRendererPrivate;
+namespace lrc {
+namespace video {
 
-/// Manage shared memory and convert it to QByteArray
-class LIB_EXPORT ShmRenderer final : public Renderer
+class ShmRenderer final : public Renderer
 {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
     Q_OBJECT
-#pragma GCC diagnostic pop
-
 public:
-    // Constructor
-    ShmRenderer(const QString& id, const QString& shmPath, const QSize& res);
-    virtual ~ShmRenderer();
+    ShmRenderer(const QString& id, const QSize& res, const QString& shmPath);
+    ~ShmRenderer();
+
+    // Renderer interface.
+    void update(const QSize& res, const QString& shmPath) override;
+    lrc::api::video::Frame currentFrame() const override;
 
-    // Mutators
     void stopShm();
     bool startShm();
 
-    // Getters
-    int fps() const;
-    virtual lrc::api::video::Frame currentFrame() const override;
-    virtual ColorSpace colorSpace() const override;
-
-    // Setters
-    void setShmPath(const QString& path);
-
-private:
-    std::unique_ptr<ShmRendererPrivate> d_ptr;
-
 public Q_SLOTS:
     void startRendering() override;
-    void stopRendering() override; // Unused
-};
+    void stopRendering() override;
 
-} // namespace Video
+private:
+    struct Impl;
+    std::unique_ptr<Impl> pimpl_;
+};
 
-#endif
+} // namespace video
+} // namespace lrc
diff --git a/src/video/renderer.cpp b/src/video/renderer.cpp
deleted file mode 100644
index cfe96fd4183ea8edf0c82867d46720f26b00c1d0..0000000000000000000000000000000000000000
--- a/src/video/renderer.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/****************************************************************************
- *    Copyright (C) 2012-2022 Savoir-faire Linux Inc.                       *
- *   Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com>      *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#include "renderer.h"
-
-// Ring
-#include "private/videorenderer_p.h"
-
-// Qt
-#include <QtCore/QMutex>
-
-Video::RendererPrivate::RendererPrivate(Video::Renderer* parent)
-    : QObject(parent)
-    , m_isRendering(false)
-    , m_pMutex(new QMutex())
-    , q_ptr(parent)
-{}
-
-Video::Renderer::Renderer(const QString& id, const QSize& res)
-    : d_ptr(new RendererPrivate(this))
-{
-    setObjectName("Renderer:" + id);
-    d_ptr->m_pSize = res;
-    d_ptr->m_Id = id;
-}
-
-Video::Renderer::~Renderer()
-{
-    delete d_ptr;
-}
-
-/*****************************************************************************
- *                                                                           *
- *                                 Getters                                   *
- *                                                                           *
- ****************************************************************************/
-
-/// Return if the rendering is currently active or not
-bool
-Video::Renderer::isRendering() const
-{
-    return d_ptr->m_isRendering;
-}
-
-/// Get mutex, in case renderer and views are not in the same thread
-QMutex*
-Video::Renderer::mutex() const
-{
-    return d_ptr->m_pMutex;
-}
-
-/// Return the current resolution
-QSize
-Video::Renderer::size() const
-{
-    return d_ptr->m_pSize;
-}
-
-/*****************************************************************************
- *                                                                           *
- *                                 Setters                                   *
- *                                                                           *
- ****************************************************************************/
-
-void
-Video::Renderer::setSize(const QSize& size) const
-{
-    d_ptr->m_pSize = size;
-}
diff --git a/src/video/renderer.h b/src/video/renderer.h
deleted file mode 100644
index cc297b70783872c2352b9fe22417154fe01387d2..0000000000000000000000000000000000000000
--- a/src/video/renderer.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
- *    Copyright (C) 2012-2022 Savoir-faire Linux Inc.                       *
- *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
- *                                                                          *
- *   This library is free software; you can redistribute it and/or          *
- *   modify it under the terms of the GNU Lesser General Public             *
- *   License as published by the Free Software Foundation; either           *
- *   version 2.1 of the License, or (at your option) any later version.     *
- *                                                                          *
- *   This library 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      *
- *   Lesser General Public License for more details.                        *
- *                                                                          *
- *   You should have received a copy of the GNU General Public License      *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-#pragma once
-
-// Base
-#include <QtCore/QObject>
-#include "api/newvideo.h"
-#include <typedefs.h>
-
-// Std
-#include <memory>
-#include <vector>
-#include <cstdint>
-
-// Qt
-class QMutex;
-struct AVFrame;
-
-namespace Video {
-
-class RendererPrivate;
-class ShmRendererPrivate;
-class ShmRenderer;
-class DirectRendererPrivate;
-class DirectRenderer;
-
-/**
- * This class is used by Renderer class to expose video data frame
- * that could be owned by instances of this class or shared.
- * If an instance carries data, "storage.size()" is greater than 0
- * and equals to "size", "ptr" is equals to "storage.data()".
- * If shared data is carried, only "ptr" and "size" are set.
- */
-struct Frame
-{
-    uint8_t* ptr {nullptr};
-    std::size_t size {0};
-    std::vector<uint8_t> storage {};
-    // Next variables are currently used with DirectRenderer only
-    unsigned int height {0};
-    unsigned int width {0};
-};
-
-/**
- * This class provide a rendering object to be used by clients
- * to get the video content. This object is not intended to be
- * extended outside of the LibRingClient.
- *
- * Each platform transparently provide its own implementation.
- */
-class LIB_EXPORT Renderer : public QObject
-{
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
-    Q_OBJECT
-#pragma GCC diagnostic pop
-
-    friend class Video::ShmRendererPrivate;
-    friend class Video::ShmRenderer;
-    friend class Video::DirectRendererPrivate;
-    friend class Video::DirectRenderer;
-
-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 QString& id, const QSize& res);
-    virtual ~Renderer();
-
-    // Getters
-    virtual bool isRendering() const;
-    virtual lrc::api::video::Frame currentFrame() const = 0;
-    virtual QSize size() const;
-    virtual QMutex* mutex() const;
-    virtual ColorSpace colorSpace() const = 0;
-#if defined(ENABLE_LIBWRAP)
-    virtual std::unique_ptr<AVFrame, void (*)(AVFrame*)> currentAVFrame() const = 0;
-#endif
-    void setSize(const QSize& size) const;
-
-Q_SIGNALS:
-    void frameUpdated(); // Emitted when a new frame is ready
-    void stopped();
-    void started();
-
-public Q_SLOTS:
-    virtual void startRendering() = 0;
-    virtual void stopRendering() = 0;
-
-private:
-    RendererPrivate* d_ptr;
-    Q_DECLARE_PRIVATE(Renderer)
-};
-
-} // namespace Video