diff --git a/src/media/video/v4l2/video_device_impl.cpp b/src/media/video/v4l2/video_device_impl.cpp
index eeb4d0363a15fdda5f72e4834cf167c1a997a66f..2741282d02792a5b153e202128a5cb76cf2dc358 100644
--- a/src/media/video/v4l2/video_device_impl.cpp
+++ b/src/media/video/v4l2/video_device_impl.cpp
@@ -441,6 +441,11 @@ VideoDeviceImpl::VideoDeviceImpl(const string& id, const std::string& path)
     , size_(-1, -1)
     , rate_(-1, 1, 0)
 {
+    if (id == DEVICE_DESKTOP) {
+        name = DEVICE_DESKTOP;
+        rate_.frame_rate = 30;
+        return;
+    }
     int fd = open(path.c_str(), O_RDWR);
     if (fd == -1)
         throw std::runtime_error("could not open device");
@@ -514,6 +519,8 @@ VideoV4l2Rate::libAvPixelformat() const
 vector<string>
 VideoDeviceImpl::getChannelList() const
 {
+    if (unique_id == DEVICE_DESKTOP)
+        return {"default"};
     vector<string> v;
     v.reserve(channels_.size());
     for (const auto& itr : channels_)
@@ -525,12 +532,26 @@ VideoDeviceImpl::getChannelList() const
 vector<VideoSize>
 VideoDeviceImpl::getSizeList(const string& channel) const
 {
+    if (unique_id == DEVICE_DESKTOP) {
+        return {VideoSize(0, 0)};
+    }
     return getChannel(channel).getSizeList();
 }
 
 vector<FrameRate>
 VideoDeviceImpl::getRateList(const string& channel, VideoSize size) const
 {
+    if (unique_id == DEVICE_DESKTOP) {
+        return {FrameRate(5),
+                FrameRate(10),
+                FrameRate(15),
+                FrameRate(20),
+                FrameRate(25),
+                FrameRate(30),
+                FrameRate(60),
+                FrameRate(120),
+                FrameRate(144)};
+    }
     return getChannel(channel).getSize(size).getRateList();
 }
 
@@ -552,6 +573,11 @@ VideoDeviceImpl::getDeviceParams() const
     params.name = name;
     params.unique_id = unique_id;
     params.input = path;
+    if (unique_id == DEVICE_DESKTOP) {
+        params.format = "x11grab";
+        params.framerate = rate_.frame_rate;
+        return params;
+    }
     params.format = "video4linux2";
     params.channel_name = channel_.name;
     params.channel = channel_.idx;
@@ -565,6 +591,10 @@ VideoDeviceImpl::getDeviceParams() const
 void
 VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
 {
+    if (unique_id == DEVICE_DESKTOP) {
+        rate_.frame_rate = params.framerate;
+        return;
+    }
     // Set preferences or fallback to defaults.
     channel_ = getChannel(params.channel_name);
     size_ = channel_.getSize({params.width, params.height});
diff --git a/src/media/video/v4l2/video_device_monitor_impl.cpp b/src/media/video/v4l2/video_device_monitor_impl.cpp
index 5e02b3d0339d835985edccf073898eb3ef5a14a8..2d9daf662857c3f852907029402d37b4632c59ec 100644
--- a/src/media/video/v4l2/video_device_monitor_impl.cpp
+++ b/src/media/video/v4l2/video_device_monitor_impl.cpp
@@ -279,6 +279,7 @@ VideoDeviceMonitor::VideoDeviceMonitor()
     , monitorImpl_(new VideoDeviceMonitorImpl(this))
 {
     monitorImpl_->start();
+    addDevice(DEVICE_DESKTOP, {});
 }
 
 VideoDeviceMonitor::~VideoDeviceMonitor() {}
diff --git a/src/media/video/video_device.h b/src/media/video/video_device.h
index 46386af941df10628668e048eeb1f9dc97b9b47b..4f2dec6e05a50ab12700c6cc96da81ab61f2374e 100644
--- a/src/media/video/video_device.h
+++ b/src/media/video/video_device.h
@@ -44,6 +44,7 @@ namespace video {
 
 using VideoSize = std::pair<unsigned, unsigned>;
 using FrameRate = rational<double>;
+static constexpr const char DEVICE_DESKTOP[] = "desktop";
 
 class VideoDeviceImpl;
 
diff --git a/src/media/video/video_device_monitor.cpp b/src/media/video/video_device_monitor.cpp
index 75a291b1ceeec1f61b9ab8601ac3ab39f04d7b3b..8542bd69eda7f62444494db4f999167263f97f6b 100644
--- a/src/media/video/video_device_monitor.cpp
+++ b/src/media/video/video_device_monitor.cpp
@@ -53,7 +53,8 @@ VideoDeviceMonitor::getDeviceList() const
     vector<string> ids;
     ids.reserve(devices_.size());
     for (const auto& dev : devices_) {
-        ids.emplace_back(dev.getDeviceId());
+        if (dev.name != DEVICE_DESKTOP)
+            ids.emplace_back(dev.getDeviceId());
     }
     return ids;
 }
@@ -213,7 +214,7 @@ VideoDeviceMonitor::addDevice(const string& id,
         }
 
         // in case there is no default device on a fresh run
-        if (defaultDevice_.empty())
+        if (defaultDevice_.empty() && id != DEVICE_DESKTOP)
             defaultDevice_ = dev.getDeviceId();
 
         devices_.emplace_back(std::move(dev));
@@ -235,13 +236,13 @@ VideoDeviceMonitor::removeDevice(const string& id)
             return;
 
         devices_.erase(it);
-
         if (defaultDevice_.find(id) != std::string::npos) {
-            if (devices_.size() == 0) {
-                defaultDevice_.clear();
-            } else {
-                defaultDevice_ = devices_[0].getDeviceId();
-            }
+            defaultDevice_.clear();
+            for (const auto& dev : devices_)
+                if (dev.name != DEVICE_DESKTOP) {
+                    defaultDevice_ = dev.getDeviceId();
+                    break;
+                }
         }
     }
     notify();
@@ -310,12 +311,16 @@ VideoDeviceMonitor::unserialize(const YAML::Node& in)
 
     // Restore the default device if present, or select the first one
     const string prefId = preferences_.empty() ? "" : preferences_[0].unique_id;
-    const string firstId = devices_.empty() ? "" : devices_[0].getDeviceId();
     const auto devIter = findDeviceById(prefId);
-    if (devIter != devices_.end()) {
+    if (devIter != devices_.end() && prefId != DEVICE_DESKTOP) {
         defaultDevice_ = devIter->getDeviceId();
     } else {
-        defaultDevice_ = firstId;
+        defaultDevice_.clear();
+        for (const auto& dev : devices_)
+            if (dev.name != DEVICE_DESKTOP) {
+                defaultDevice_ = dev.getDeviceId();
+                break;
+            }
     }
 }
 
diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp
index d91f1b6bcc42240ff10b4dadfc38ebe2b62c8097..f4af01384253b20017f342dab8d3c81139bb4809 100644
--- a/src/media/video/video_input.cpp
+++ b/src/media/video/video_input.cpp
@@ -396,8 +396,7 @@ VideoInput::initX11(std::string display)
     size_t space = display.find(' ');
 
     clearOptions();
-    decOpts_.format = "x11grab";
-    decOpts_.framerate = 25;
+    decOpts_ = jami::getVideoDeviceMonitor().getDeviceParams(DEVICE_DESKTOP);
 
     if (space != std::string::npos) {
         std::istringstream iss(display.substr(space + 1));
@@ -428,7 +427,7 @@ VideoInput::initAVFoundation(const std::string& display)
     decOpts_.pixel_format = "nv12";
     decOpts_.name = "Capture screen 0";
     decOpts_.input = "Capture screen 0";
-    decOpts_.framerate = 30;
+    decOpts_.framerate = jami::getVideoDeviceMonitor().getDeviceParams(DEVICE_DESKTOP).framerate;
 
     if (space != std::string::npos) {
         std::istringstream iss(display.substr(space + 1));
@@ -449,9 +448,7 @@ VideoInput::initGdiGrab(const std::string& params)
 {
     size_t space = params.find(' ');
     clearOptions();
-    decOpts_.format = "gdigrab";
-    decOpts_.input = "desktop";
-    decOpts_.framerate = 30;
+    decOpts_ = jami::getVideoDeviceMonitor().getDeviceParams(DEVICE_DESKTOP);
 
     if (space != std::string::npos) {
         std::istringstream iss(params.substr(space + 1));
diff --git a/src/media/video/winvideo/video_device_impl.cpp b/src/media/video/winvideo/video_device_impl.cpp
index e244d40079f75916d60bc63daf04e39d5d1efe89..9af9dc8ce3dea5dfe2e2d6c1ba82f43dff828ef3 100644
--- a/src/media/video/winvideo/video_device_impl.cpp
+++ b/src/media/video/winvideo/video_device_impl.cpp
@@ -64,6 +64,7 @@ private:
     std::vector<VideoSize> sizeList_;
     std::map<VideoSize, std::vector<FrameRate>> rateList_;
     std::map<VideoSize, AM_MEDIA_TYPE*> capMap_;
+    FrameRate desktopFrameRate_ = {30};
 
     void fail(const std::string& error);
 };
@@ -79,6 +80,21 @@ VideoDeviceImpl::VideoDeviceImpl(const std::string& id)
 void
 VideoDeviceImpl::setup()
 {
+    if (id == DEVICE_DESKTOP) {
+        name = DEVICE_DESKTOP;
+        VideoSize size {0, 0};
+        sizeList_.emplace_back(size);
+        rateList_[size] = {FrameRate(5),
+                           FrameRate(10),
+                           FrameRate(15),
+                           FrameRate(20),
+                           FrameRate(25),
+                           FrameRate(30),
+                           FrameRate(60),
+                           FrameRate(120),
+                           FrameRate(144)};
+        return;
+    }
     HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
                                   nullptr,
                                   CLSCTX_INPROC_SERVER,
@@ -264,6 +280,12 @@ VideoDeviceImpl::getDeviceParams() const
     params.name = name;
     params.unique_id = id;
     params.input = id;
+    if (id == DEVICE_DESKTOP) {
+        params.format = "gdigrab";
+        params.framerate = desktopFrameRate_;
+        return params;
+    }
+
     params.format = "dshow";
 
     AM_MEDIA_TYPE* pmt;
@@ -282,6 +304,10 @@ VideoDeviceImpl::getDeviceParams() const
 void
 VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
 {
+    if (id == DEVICE_DESKTOP) {
+        desktopFrameRate_ = params.framerate;
+        return;
+    }
     if (params.width and params.height) {
         auto pmt = capMap_.at(std::make_pair(params.width, params.height));
         if (pmt != nullptr) {
diff --git a/src/media/video/winvideo/video_device_monitor_impl.cpp b/src/media/video/winvideo/video_device_monitor_impl.cpp
index c4abebbfdd90b3ceeed902b453db80c79ce437e9..cc23a92b646897bbd999c3b414e76c9f7f39d6a4 100644
--- a/src/media/video/winvideo/video_device_monitor_impl.cpp
+++ b/src/media/video/winvideo/video_device_monitor_impl.cpp
@@ -293,6 +293,7 @@ VideoDeviceMonitor::VideoDeviceMonitor()
     , monitorImpl_(new VideoDeviceMonitorImpl(this))
 {
     monitorImpl_->start();
+    addDevice(DEVICE_DESKTOP, {});
 }
 
 VideoDeviceMonitor::~VideoDeviceMonitor() {}