diff --git a/contrib/src/ffmpeg/package.json b/contrib/src/ffmpeg/package.json
index 8aec16c575aea4ba1cd588767b2349e0940598fe..c042b93c31d7a6ba35e7a021b4bf17ee8bf2e82e 100644
--- a/contrib/src/ffmpeg/package.json
+++ b/contrib/src/ffmpeg/package.json
@@ -16,7 +16,8 @@
         "libopusdec-enable-FEC.patch",
         "windows-configure.patch",
         "windows-configure-ffnvcodec.patch",
-        "windows-configure-libmfx.patch"
+        "windows-configure-libmfx.patch",
+        "windows-dxgi-support.patch"
     ],
     "win_patches": [
     ],
diff --git a/contrib/src/ffmpeg/windows-configure-make.sh b/contrib/src/ffmpeg/windows-configure-make.sh
index 04c0688a7334b80823d309386cda6c7e0c74ffa8..272f4d27ad81de8b67c68d5cf6fd867ff4e7eaca 100644
--- a/contrib/src/ffmpeg/windows-configure-make.sh
+++ b/contrib/src/ffmpeg/windows-configure-make.sh
@@ -145,7 +145,7 @@ if [ "$1" == "uwp" ]; then
             OUTDIR=Output/Windows10/x86
     fi
 elif [ "$1" == "win32" ]; then
-    EXTRACFLAGS='-MD -D_WINDLL -I../../../../../msvc/include -I../../../../../msvc/include/opus -I../../../../../msvc/include/vpx -I../../../../../msvc/include/ffnvcodec -I../../../../../msvc/include/mfx' 
+    EXTRACFLAGS='-MD -D_WINDLL -I../../../../../msvc/include -I../../../../../msvc/include/opus -I../../../../../msvc/include/vpx -I../../../../../msvc/include/ffnvcodec -I../../../../../msvc/include/mfx  -D_WIN32_WINNT=0x0A00'
     FFMPEGCONF+='
                 --enable-libvpx
                 --enable-encoder=libvpx_vp8
@@ -154,7 +154,8 @@ elif [ "$1" == "win32" ]; then
     FFMPEGCONF+='
                 --enable-indev=dshow
                 --enable-indev=gdigrab
-                --enable-dxva2'
+                --enable-dxva2
+                --enable-indev=dxgigrab'
     FFMPEGCONF+='
                 --enable-ffnvcodec
                 --enable-cuvid
@@ -199,6 +200,6 @@ pwd
 FFMPEGCONF=$(echo $FFMPEGCONF | sed -e "s/[[:space:]]\+/ /g")
 set -x
 set -e
-../../../configure $FFMPEGCONF --extra-cflags="${EXTRACFLAGS}" --extra-ldflags="${EXTRALDFLAGS}" --prefix="${PREFIX}"
+../../../configure $FFMPEGCONF --extra-cflags="${EXTRACFLAGS}" --extra-ldflags="${EXTRALDFLAGS}" --prefix="${PREFIX}" --extra-cxxflags="-std:c++17"
 make -j8 install
 cd ../../..
diff --git a/contrib/src/ffmpeg/windows-dxgi-support.patch b/contrib/src/ffmpeg/windows-dxgi-support.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4458c0315604ecb9daafc2e08e8ef633b1054f0f
--- /dev/null
+++ b/contrib/src/ffmpeg/windows-dxgi-support.patch
@@ -0,0 +1,957 @@
+From 9055aa8b78fcd8e913642ffe21759579283ae1bb Mon Sep 17 00:00:00 2001
+From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
+Date: Thu, 29 Dec 2022 12:59:19 -0300
+Subject: [PATCH] Add dxgi support
+
+---
+ configure                        |   1 +
+ libavdevice/Makefile             |   4 +
+ libavdevice/alldevices.c         |   1 +
+ libavdevice/d3dHelpers.h         |  59 +++++++++
+ libavdevice/direct3d11.interop.h |  51 ++++++++
+ libavdevice/dxgigrab.cpp         | 218 +++++++++++++++++++++++++++++++
+ libavdevice/dxgigrab.h           |  83 ++++++++++++
+ libavdevice/dxgigrab_c.c         |  59 +++++++++
+ libavdevice/dxgigrab_c.h         |  98 ++++++++++++++
+ libavdevice/windows_capture.cpp  | 184 ++++++++++++++++++++++++++
+ libavdevice/windows_capture.h    |  82 ++++++++++++
+ 11 files changed, 840 insertions(+)
+ create mode 100644 libavdevice/d3dHelpers.h
+ create mode 100644 libavdevice/direct3d11.interop.h
+ create mode 100644 libavdevice/dxgigrab.cpp
+ create mode 100644 libavdevice/dxgigrab.h
+ create mode 100644 libavdevice/dxgigrab_c.c
+ create mode 100644 libavdevice/dxgigrab_c.h
+ create mode 100644 libavdevice/windows_capture.cpp
+ create mode 100644 libavdevice/windows_capture.h
+
+diff --git a/configure b/configure
+index 6b5ef6332e..3606ce5bc3 100755
+--- a/configure
++++ b/configure
+@@ -3509,6 +3509,7 @@ fbdev_outdev_deps="linux_fb_h"
+ gdigrab_indev_deps="CreateDIBSection"
+ gdigrab_indev_extralibs="-lgdi32"
+ gdigrab_indev_select="bmp_decoder"
++dxgigrab_indev_extralibs="-ldxgi -ld3d11"
+ iec61883_indev_deps="libiec61883"
+ jack_indev_deps="libjack"
+ jack_indev_deps_any="sem_timedwait dispatch_dispatch_h"
+diff --git a/libavdevice/Makefile b/libavdevice/Makefile
+index 53efda0514..a6fb30cdea 100644
+--- a/libavdevice/Makefile
++++ b/libavdevice/Makefile
+@@ -28,6 +28,7 @@ OBJS-$(CONFIG_FBDEV_INDEV)               += fbdev_dec.o \
+ OBJS-$(CONFIG_FBDEV_OUTDEV)              += fbdev_enc.o \
+                                             fbdev_common.o
+ OBJS-$(CONFIG_GDIGRAB_INDEV)             += gdigrab.o
++OBJS-$(CONFIG_DXGIGRAB_INDEV)            += windows_capture.o dxgigrab.o dxgigrab_c.o
+ OBJS-$(CONFIG_IEC61883_INDEV)            += iec61883.o
+ OBJS-$(CONFIG_JACK_INDEV)                += jack.o timefilter.o
+ OBJS-$(CONFIG_KMSGRAB_INDEV)             += kmsgrab.o
+@@ -70,5 +71,8 @@ SKIPHEADERS-$(CONFIG_V4L2_INDEV)         += v4l2-common.h
+ SKIPHEADERS-$(CONFIG_V4L2_OUTDEV)        += v4l2-common.h
+ SKIPHEADERS-$(CONFIG_ALSA)               += alsa.h
+ SKIPHEADERS-$(CONFIG_SNDIO)              += sndio.h
++SKIPHEADERS-$(CONFIG_DXGIGRAB_INDEV)     += dxgigrab.h \
++                                            windows_capture.h \
++                                            dxgigrab_c.h
+ 
+ TESTPROGS-$(CONFIG_JACK_INDEV)           += timefilter
+diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c
+index 22323a0a44..fb0a37513b 100644
+--- a/libavdevice/alldevices.c
++++ b/libavdevice/alldevices.c
+@@ -35,6 +35,7 @@ extern const AVInputFormat  ff_dshow_demuxer;
+ extern const AVInputFormat  ff_fbdev_demuxer;
+ extern const AVOutputFormat ff_fbdev_muxer;
+ extern const AVInputFormat  ff_gdigrab_demuxer;
++extern const AVInputFormat  ff_dxgigrab_demuxer;
+ extern const AVInputFormat  ff_iec61883_demuxer;
+ extern const AVInputFormat  ff_jack_demuxer;
+ extern const AVInputFormat  ff_kmsgrab_demuxer;
+diff --git a/libavdevice/d3dHelpers.h b/libavdevice/d3dHelpers.h
+new file mode 100644
+index 0000000000..d8d2c003ec
+--- /dev/null
++++ b/libavdevice/d3dHelpers.h
+@@ -0,0 +1,59 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#pragma once
++
++#include <winrt/Windows.UI.Composition.h>
++#include <windows.ui.composition.interop.h>
++#include <d2d1_1.h>
++
++inline auto
++CreateD3DDevice(
++    D3D_DRIVER_TYPE const type,
++    winrt::com_ptr<ID3D11Device>& device)
++{
++    WINRT_ASSERT(!device);
++
++    UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
++
++    return D3D11CreateDevice(
++        nullptr,
++        type,
++        nullptr,
++        flags,
++        nullptr, 0,
++        D3D11_SDK_VERSION,
++        device.put(),
++        nullptr,
++        nullptr);
++}
++
++inline auto
++CreateD3DDevice()
++{
++    winrt::com_ptr<ID3D11Device> device;
++    HRESULT hr = CreateD3DDevice(D3D_DRIVER_TYPE_HARDWARE, device);
++
++    if (DXGI_ERROR_UNSUPPORTED == hr)
++    {
++        hr = CreateD3DDevice(D3D_DRIVER_TYPE_WARP, device);
++    }
++
++    winrt::check_hresult(hr);
++    return device;
++}
+diff --git a/libavdevice/direct3d11.interop.h b/libavdevice/direct3d11.interop.h
+new file mode 100644
+index 0000000000..62c9b0843e
+--- /dev/null
++++ b/libavdevice/direct3d11.interop.h
+@@ -0,0 +1,51 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#pragma once
++#include <winrt/windows.graphics.directx.direct3d11.h>
++
++extern "C"
++{
++    HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(::IDXGIDevice* dxgiDevice,
++        ::IInspectable** graphicsDevice);
++
++    HRESULT __stdcall CreateDirect3D11SurfaceFromDXGISurface(::IDXGISurface* dgxiSurface,
++        ::IInspectable** graphicsSurface);
++}
++
++struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
++    IDirect3DDxgiInterfaceAccess : ::IUnknown
++{
++    virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
++};
++
++inline auto CreateDirect3DDevice(IDXGIDevice* dxgi_device)
++{
++    winrt::com_ptr<::IInspectable> d3d_device;
++    winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(dxgi_device, d3d_device.put()));
++    return d3d_device.as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>();
++}
++
++template <typename T>
++auto GetDXGIInterfaceFromObject(winrt::Windows::Foundation::IInspectable const& object)
++{
++    auto access = object.as<IDirect3DDxgiInterfaceAccess>();
++    winrt::com_ptr<T> result;
++    winrt::check_hresult(access->GetInterface(winrt::guid_of<T>(), result.put_void()));
++    return result;
++}
+diff --git a/libavdevice/dxgigrab.cpp b/libavdevice/dxgigrab.cpp
+new file mode 100644
+index 0000000000..365ba4f9aa
+--- /dev/null
++++ b/libavdevice/dxgigrab.cpp
+@@ -0,0 +1,218 @@
++/*
++ * DXGI video grab interface
++ *
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * DXGI frame device demuxer
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#include "dxgigrab.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++#include <libavutil/parseutils.h>
++#ifdef __cplusplus
++}
++#endif
++
++static BOOL CALLBACK enumMonitor(HMONITOR handle, HDC hdc, LPRECT rect,
++                    LPARAM lParam)
++{
++    MonitorData* monitorData = reinterpret_cast<MonitorData*>(lParam);
++
++    if (monitorData->curId == 0 || monitorData->desiredId == monitorData->curId) {
++        monitorData->rect = *rect;
++        monitorData->id = monitorData->curId;
++
++        monitorData->hmnt = handle;
++    }
++
++    return (monitorData->desiredId > monitorData->curId++);
++}
++
++int dxgigrab_read_header(AVFormatContext *s1)
++{
++    struct dxgigrab *s = static_cast<dxgigrab*>(s1->priv_data);
++    if (!s->internal_struct)
++        s->internal_struct = new dxgigrab_internal();
++    struct dxgigrab_internal* x_internal = static_cast<dxgigrab_internal*>(s->internal_struct);
++    MonitorData monitorData;
++    monitorData.rect.top = 0;
++    monitorData.rect.left = 0;
++    monitorData.rect.bottom = 0;
++    monitorData.rect.right = 0;
++    const char *name     = NULL;
++    AVStream   *st       = NULL;
++
++    if (!strncmp(s1->url, "title=", 6)) {
++        name = s1->url + 6;
++        s->hwnd = FindWindow(NULL, name);
++        if (!s->hwnd) {
++            av_log(s1, AV_LOG_ERROR,
++                   "Can't find window '%s', aborting.\n", name);
++            return AVERROR_EXTERNAL;
++        }
++    } else {
++        s->hwnd = NULL;
++        char *display_number = av_strdup(s1->url);
++        if (!sscanf(s1->url, "%[^+]+%d,%d ", display_number, &s->offset_x, &s->offset_y)) {
++            av_log(s1, AV_LOG_ERROR,
++                "Please use \"<screenNumber>+<X,Y> <WidthxHeight>\" or \"title=<windowname>\" to specify your target.\n");
++            return AVERROR_EXTERNAL;
++        }
++        if (s->offset_x || s->offset_y) {
++            av_log(s1,
++                   AV_LOG_ERROR,
++                   "This device does not support partial screen sharing.\n");
++            return AVERROR_PATCHWELCOME;
++        }
++        monitorData.desiredId = std::stoi(display_number);
++        av_freep(&display_number);
++        try {
++            LPARAM lParam = reinterpret_cast<LPARAM>(&monitorData);
++            EnumDisplayMonitors(NULL, NULL, enumMonitor, lParam);
++        } catch (...) {
++        }
++    }
++
++    s->hmnt = monitorData.hmnt;
++    s->rect = monitorData.rect;
++
++    if (!s->hmnt && !s->hwnd) {
++        av_log(s1, AV_LOG_ERROR,
++               "Please use \"<screenNumber>+<X,Y> <WidthxHeight>\" or \"title=<windowname>\" to "
++               "specify your target.\n");
++        return AVERROR_EXTERNAL;
++    }
++
++    bool openWindow = true;
++    if (!s1->nb_streams) {
++        st = avformat_new_stream(s1, NULL);
++    } else {
++        openWindow = false;
++        st = s1->streams[0];
++    }
++    if (!st) {
++        return AVERROR(ENOMEM);
++    }
++
++    std::lock_guard lk(x_internal->mtx);
++    if (openWindow) {
++        auto d3dDevice = CreateD3DDevice();
++        auto dxgiDevice = d3dDevice.as<IDXGIDevice>();
++        auto m_device = CreateDirect3DDevice(dxgiDevice.get());
++
++        auto activation_factory = winrt::get_activation_factory<winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
++        auto interop_factory = activation_factory.as<IGraphicsCaptureItemInterop>();
++        winrt::Windows::Graphics::Capture::GraphicsCaptureItem windowItem = { nullptr };
++
++        try {
++            if (s->hwnd) {
++                winrt::check_hresult(interop_factory
++                    ->CreateForWindow(s->hwnd, // we should have create for display too
++                                    winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
++                                    reinterpret_cast<void**>(winrt::put_abi(windowItem))));
++            } else if (s->hmnt) {
++                winrt::check_hresult(interop_factory
++                    ->CreateForMonitor(s->hmnt, // we should have create for display too
++                                    winrt::guid_of<ABI::Windows::Graphics::Capture::IGraphicsCaptureItem>(),
++                                    reinterpret_cast<void**>(winrt::put_abi(windowItem))));
++            }
++        }  catch (winrt::hresult_error &err) {
++            av_log(s, AV_LOG_ERROR, "CreateForWindow failed: %s\n", err.message().c_str());
++            return AVERROR_EXTERNAL;
++        } catch (...) {
++            av_log(s, AV_LOG_ERROR, "CreateForWindow failed\n");
++            return AVERROR_EXTERNAL;
++        }
++        av_log(s, AV_LOG_ERROR, "CreateForWindow success\n");
++
++        x_internal->m_capture.reset(new WindowsCapture(m_device, windowItem, monitorData));
++        x_internal->m_capture->StartCapture();
++        x_internal->m_capture->checkNewFrameArrived();
++        x_internal->m_capture->window = name ? name : "";
++        x_internal->windowName = name ? name : "";
++    }
++
++    s->time_base   = av_inv_q(s->framerate);
++
++    avpriv_set_pts_info(st, 64, 1, 1000000);
++
++    s->width = x_internal->m_capture->m_DeviceSize.Width;
++    s->height = x_internal->m_capture->m_DeviceSize.Height;
++
++    x_internal->m_capture->screen.first = monitorData.hmnt;
++    x_internal->m_capture->screen.second = monitorData.rect;
++
++    s->time_frame = av_gettime_relative();
++
++    st->avg_frame_rate = av_inv_q(s->time_base);
++
++    auto frame_size_bits = (int64_t)s->width * s->height * 4 * 8;
++    if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) {
++        av_log(s, AV_LOG_ERROR, "Captured area is too large\n");
++        return AVERROR_PATCHWELCOME;
++    }
++    s->frame_size = frame_size_bits / 8;
++
++    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
++    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
++    st->codecpar->width      = s->width;
++    st->codecpar->height     = s->height;
++    st->codecpar->format     = AV_PIX_FMT_RGBA;
++    st->codecpar->bit_rate   = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den);
++
++    return 0;
++}
++
++int dxgigrab_read_packet(AVFormatContext *s1, AVPacket *pkt)
++{
++    struct dxgigrab *s = static_cast<dxgigrab*>(s1->priv_data);
++    struct dxgigrab_internal *x_internal = static_cast<dxgigrab_internal*>(s->internal_struct);
++    std::lock_guard lk(x_internal->mtx);
++    int ret = 0;
++    int64_t pts = av_gettime();
++
++    if (!x_internal->m_capture)
++        return 0; // If m_capture not available, return empty frame
++    ret = x_internal->m_capture->GetPkt(pkt);
++    if (ret < 0)
++        return ret;
++    pkt->dts = pkt->pts = pts;
++
++    return ret;
++}
++
++int dxgigrab_read_close(AVFormatContext *s1)
++{
++    struct dxgigrab* s = static_cast<dxgigrab*>(s1->priv_data);
++    struct dxgigrab_internal* x_internal = static_cast<dxgigrab_internal*>(s->internal_struct);
++    std::lock_guard lk(x_internal->mtx);
++
++    if (!x_internal->m_capture)
++        return 0; // If m_capture not available, no need to close it
++    x_internal->m_capture->Close();
++
++    return 0;
++}
+diff --git a/libavdevice/dxgigrab.h b/libavdevice/dxgigrab.h
+new file mode 100644
+index 0000000000..a247077e7d
+--- /dev/null
++++ b/libavdevice/dxgigrab.h
+@@ -0,0 +1,83 @@
++/*
++ * DXGI video grab interface
++ *
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * DXGI frame device demuxer
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#ifndef AVDEVICE_DXGI_H
++#define AVDEVICE_DXGI_H
++
++#include <stdlib.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++#include "dxgigrab_c.h"
++#ifdef __cplusplus
++}
++#endif
++
++#include <Unknwn.h>
++#include <inspectable.h>
++
++// WinRT
++#include <winrt/Windows.Foundation.h>
++#include <winrt/Windows.System.h>
++#include <winrt/Windows.UI.h>
++#include <winrt/Windows.UI.Composition.h>
++#include <winrt/Windows.UI.Composition.Desktop.h>
++#include <winrt/Windows.UI.Popups.h>
++#include <winrt/Windows.Graphics.Capture.h>
++#include <winrt/Windows.Graphics.DirectX.h>
++#include <winrt/Windows.Graphics.DirectX.Direct3d11.h>
++#include <windows.graphics.capture.interop.h>
++#include <windows.graphics.capture.h>
++
++#include <windows.ui.composition.interop.h>
++#include <DispatcherQueue.h>
++
++// STL
++#include <atomic>
++#include <memory>
++#include <mutex>
++
++// D3D
++#include <d3d11_4.h>
++#include <dxgi1_6.h>
++#include <d2d1_3.h>
++#include <wincodec.h>
++
++// Internal
++#include "d3dHelpers.h"
++#include "direct3d11.interop.h"
++#include "windows_capture.h"
++
++struct dxgigrab_internal {
++    std::unique_ptr<WindowsCapture> m_capture{ nullptr };
++    std::string windowName;
++    std::mutex mtx;
++};
++
++#endif /* AVDEVICE_DXGI_H */
+diff --git a/libavdevice/dxgigrab_c.c b/libavdevice/dxgigrab_c.c
+new file mode 100644
+index 0000000000..c53d757abd
+--- /dev/null
++++ b/libavdevice/dxgigrab_c.c
+@@ -0,0 +1,59 @@
++/*
++ * DXGI video grab interface
++ *
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * DXGI frame device demuxer
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#include "dxgigrab_c.h"
++
++#define OFFSET(x) offsetof(struct dxgigrab, x)
++#define DEC AV_OPT_FLAG_DECODING_PARAM
++static const AVOption options[] = {
++    { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, DEC },
++    { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
++    { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
++    { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
++    { NULL },
++};
++
++static const AVClass dxgigrab_class = {
++    .class_name = "DXGIgrab indev",
++    .item_name  = av_default_item_name,
++    .option     = options,
++    .version    = LIBAVUTIL_VERSION_INT,
++    .category   = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,
++};
++
++/** dxgi grabber device demuxer declaration */
++AVInputFormat ff_dxgigrab_demuxer = {
++    .name           = "dxgigrab",
++    .long_name      = NULL_IF_CONFIG_SMALL("DXGI API Windows frame grabber"),
++    .priv_data_size = sizeof(struct dxgigrab),
++    .read_header    = dxgigrab_read_header,
++    .read_packet    = dxgigrab_read_packet,
++    .read_close     = dxgigrab_read_close,
++    .flags          = AVFMT_NOFILE,
++    .priv_class     = &dxgigrab_class,
++};
+diff --git a/libavdevice/dxgigrab_c.h b/libavdevice/dxgigrab_c.h
+new file mode 100644
+index 0000000000..d624ca0683
+--- /dev/null
++++ b/libavdevice/dxgigrab_c.h
+@@ -0,0 +1,98 @@
++/*
++ * DXGI video grab interface
++ *
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * DXGI frame device demuxer
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#ifndef AVDEVICE_DXGI_C_H
++#define AVDEVICE_DXGI_C_H
++
++#include <stdlib.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include "libavformat/internal.h"
++#include "config.h"
++#include "libavutil/opt.h"
++#include "libavutil/time.h"
++
++#include <windows.h>
++
++/**
++ * DXGI Device Demuxer context
++ */
++struct dxgigrab {
++    const AVClass             *avclass;     /**< Class for private options */
++
++    int                        frame_size;  /**< Size in bytes of the frame pixel data */
++    AVRational                 time_base;   /**< Time base */
++    int64_t                    time_frame;  /**< Current time */
++
++    AVRational                 framerate;   /**< Capture framerate (private option) */
++    int                        width;       /**< Width of the grab frame (private option) */
++    int                        height;      /**< Height of the grab frame (private option) */
++    int                        offset_x;    /**< Capture x offset (private option) */
++    int                        offset_y;    /**< Capture y offset (private option) */
++
++    HWND                       hwnd;        /**< Handle of the Window for the grab */
++    HMONITOR                   hmnt;        /**< Handle of the Screen for the grab */
++    RECT                       rect;        /**< Rect of the Screen for the grab */
++
++    void* internal_struct;
++};
++
++/**
++ * Initializes the dxgi grab device demuxer (public device demuxer API).
++ *
++ * @param s1 Context from avformat core
++ * @return AVERROR_IO error, 0 success
++ */
++int dxgigrab_read_header(AVFormatContext *s1);
++
++/**
++ * Grabs a frame from dxgi (public device demuxer API).
++ *
++ * @param s1 Context from avformat core
++ * @param pkt Packet holding the grabbed frame
++ * @return frame size in bytes
++ */
++int dxgigrab_read_packet(AVFormatContext *s1, AVPacket *pkt);
++
++
++/**
++ * Closes dxgi frame grabber (public device demuxer API).
++ *
++ * @param s1 Context from avformat core
++ * @return 0 success, !0 failure
++ */
++int dxgigrab_read_close(AVFormatContext *s1);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* AVDEVICE_DXGI_C_H */
+diff --git a/libavdevice/windows_capture.cpp b/libavdevice/windows_capture.cpp
+new file mode 100644
+index 0000000000..9eaf8cf222
+--- /dev/null
++++ b/libavdevice/windows_capture.cpp
+@@ -0,0 +1,184 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#include "dxgigrab.h"
++
++#include <d3d11.h>
++
++using namespace winrt;
++using namespace Windows;
++using namespace Windows::Foundation;
++using namespace Windows::System;
++using namespace Windows::Graphics;
++using namespace Windows::Graphics::Capture;
++using namespace Windows::Graphics::DirectX;
++using namespace Windows::Graphics::DirectX::Direct3D11;
++using namespace Windows::Foundation::Numerics;
++using namespace Windows::UI;
++using namespace Windows::UI::Composition;
++
++WindowsCapture::WindowsCapture(
++    IDirect3DDevice const& device,
++    GraphicsCaptureItem const& item,
++    MonitorData& monitorData)
++{
++    m_item = item;
++    m_device = device;
++
++    m_d3dDevice = GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
++    m_d3dDevice->GetImmediateContext(m_d3dContext.put());
++    screen.first = monitorData.hmnt;
++    screen.second = monitorData.rect;
++
++    m_DeviceSize = m_item.Size();
++
++    // Create framepool, define pixel format (DXGI_FORMAT_B8G8R8A8_UNORM), and frame size.
++    m_framePool = Direct3D11CaptureFramePool::Create(
++        m_device,
++        DirectXPixelFormat::R8G8B8A8UIntNormalized,
++        2,
++        m_DeviceSize);
++    m_session = m_framePool.CreateCaptureSession(m_item);
++    auto sup = m_session.IsSupported();
++}
++
++// Start sending capture frames
++void
++WindowsCapture::StartCapture()
++{
++    std::lock_guard<std::mutex> lk(mtx_);
++    running_ = true;
++    m_session.StartCapture();
++}
++
++// Process captured frames
++void
++WindowsCapture::Close()
++{
++    std::lock_guard<std::mutex> lk(mtx_);
++    running_ = false;
++    if (texture) {
++        texture->Release();
++    }
++    m_framePool.Close();
++    m_session.Close();
++    m_d3dContext->ClearState();
++    m_d3dContext->Flush();
++    m_d3dDevice->Release();
++
++    texture = nullptr;
++    m_framePool = nullptr;
++    m_session = nullptr;
++    m_item = nullptr;
++}
++
++bool
++WindowsCapture::checkNewFrameArrived()
++{
++    std::lock_guard<std::mutex> lk(mtx_);
++    if (!running_)
++        return 0;
++    auto shouldResize = false;
++
++    auto frame = m_framePool.TryGetNextFrame();
++    if (!frame)
++        return 0;
++
++    auto frameSurface = GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
++
++    D3D11_TEXTURE2D_DESC desc;
++    frameSurface->GetDesc(&desc);
++    auto frameContentSize = frame.ContentSize();
++    if (desc.Width <= 0 || desc.Height <= 0)
++        return 0;
++
++    shouldResize = frameContentSize.Width != m_DeviceSize.Width || frameContentSize.Height != m_DeviceSize.Height;
++
++    if (shouldResize) {
++        m_DeviceSize.Width = frameContentSize.Width;
++        m_DeviceSize.Height = frameContentSize.Height;
++        m_framePool.Recreate(m_device, DirectXPixelFormat::R8G8B8A8UIntNormalized, 2, m_DeviceSize);
++        return false;
++    }
++
++    texDesc.Width = desc.Width;
++    texDesc.Height = desc.Height;
++    texDesc.MipLevels = desc.MipLevels;
++    texDesc.ArraySize = desc.ArraySize;
++    texDesc.Format = desc.Format;
++    texDesc.SampleDesc = desc.SampleDesc;
++    texDesc.Usage = D3D11_USAGE_STAGING;
++    texDesc.BindFlags = 0;
++    texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
++    texDesc.MiscFlags = 0;
++
++    m_d3dDevice->CreateTexture2D(&texDesc, nullptr, &texture);
++
++    // copy the texture to a staging resource
++    m_d3dContext->CopyResource(texture, frameSurface.get());
++
++    return 1;
++}
++
++int
++WindowsCapture::GetPkt(AVPacket *pkt)
++{
++    if (!checkNewFrameArrived() || !running_ || !texture)
++        return 0;
++    std::lock_guard<std::mutex> lk(mtx_);
++
++    // now, map the staging resource TO CPU
++    D3D11_MAPPED_SUBRESOURCE mapInfo;
++    m_d3dContext->Map(
++        texture,
++        0,
++        D3D11_MAP_READ,
++        0,
++        &mapInfo);
++
++    m_d3dContext->Unmap(texture, 0);
++
++    auto ret = av_new_packet(pkt, mapInfo.DepthPitch);
++    if (ret < 0) {
++        if (mapInfo.DepthPitch) {
++            av_packet_unref(pkt);
++        }
++        texture->Release();
++        texture = nullptr;
++        return ret;
++    }
++
++    auto idx = 0;
++    for (auto y = 0; y < m_DeviceSize.Height; y++) {
++        for (auto x = 0; x < m_DeviceSize.Width * 4; x++) {
++            pkt->data[idx] = static_cast<uint8_t*>(mapInfo.pData)[y * mapInfo.RowPitch + x];
++            idx++;
++        }
++    }
++
++    texture->Release();
++    texture = nullptr;
++
++    return 0;
++}
+diff --git a/libavdevice/windows_capture.h b/libavdevice/windows_capture.h
+new file mode 100644
+index 0000000000..3e9269ed58
+--- /dev/null
++++ b/libavdevice/windows_capture.h
+@@ -0,0 +1,82 @@
++/*
++ * This file is part of FFmpeg.
++ *
++ * Copyright (C) 2022 Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ *
++ * FFmpeg 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.
++ *
++ * FFmpeg 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 Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @author Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
++ */
++
++#pragma once
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++#include <libavutil/hwcontext_d3d11va.h>
++#ifdef __cplusplus
++}
++#endif
++
++#include <mutex>
++#include <memory>
++
++#include <windows.h>
++
++struct MonitorData {
++    HMONITOR hmnt = NULL;
++    RECT rect;
++    int id = 0;
++    int curId = 0;
++    int desiredId = 0;
++};
++
++class WindowsCapture
++{
++public:
++    WindowsCapture(
++        winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice const& device,
++        winrt::Windows::Graphics::Capture::GraphicsCaptureItem const& item,
++        MonitorData& monitorData);
++    ~WindowsCapture() { Close(); }
++
++    void StartCapture();
++
++    int GetPkt(AVPacket *pkt);
++
++    void Close();
++    std::string window;
++
++    bool checkNewFrameArrived();
++    winrt::Windows::Graphics::SizeInt32 m_DeviceSize;
++    std::pair<bool, RECT> screen;
++
++private:
++    winrt::Windows::Graphics::Capture::GraphicsCaptureItem m_item{ nullptr };
++    winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool m_framePool{ nullptr };
++    winrt::Windows::Graphics::Capture::GraphicsCaptureSession m_session{ nullptr };
++
++    winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice m_device {nullptr};
++    winrt::com_ptr<ID3D11Device> m_d3dDevice{nullptr};
++    winrt::com_ptr<ID3D11DeviceContext> m_d3dContext {nullptr};
++
++    D3D11_TEXTURE2D_DESC texDesc;
++    ID3D11Texture2D *texture {nullptr};
++
++    std::mutex mtx_;
++    bool running_;
++};
+--
+2.30.2.windows.1
+
diff --git a/src/media/media_decoder.cpp b/src/media/media_decoder.cpp
index cc8ad30f4f4f927f7c098fb86e6a0013090bc5fc..f9e5d04a2850ac240454bd8824cbcf4741659fc2 100644
--- a/src/media/media_decoder.cpp
+++ b/src/media/media_decoder.cpp
@@ -350,7 +350,7 @@ MediaDemuxer::decode()
                                                                                     av_packet_free(
                                                                                         &p);
                                                                             });
-    if (inputParams_.format == "x11grab") {
+    if (inputParams_.format == "x11grab" || inputParams_.format == "dxgigrab") {
         auto ret = inputCtx_->iformat->read_header(inputCtx_);
         if (ret == AVERROR_EXTERNAL) {
             JAMI_ERR("Couldn't read frame: %s\n", libav_utils::getError(ret).c_str());
diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp
index aacf8a3f5f0101b774ca1c5d9ad383779ad1f219..d56c291b58fcf7dc71a1a6a229b2855e77856bf8 100644
--- a/src/media/video/video_input.cpp
+++ b/src/media/video/video_input.cpp
@@ -285,7 +285,7 @@ VideoInput::createDecoder()
         [](void* data) -> int { return not static_cast<VideoInput*>(data)->isCapturing(); }, this);
 
     bool ready = false, restartSink = false;
-    if (decOpts_.format == "x11grab" && !decOpts_.is_area) {
+    if ((decOpts_.format == "x11grab" || decOpts_.format == "dxgigrab") && !decOpts_.is_area) {
         decOpts_.width = 0;
         decOpts_.height = 0;
     }
@@ -417,7 +417,6 @@ VideoInput::initX11(const std::string& display)
         p.input = display.substr(1, space);
         if (p.window_id.empty()) {
             p.input = display.substr(0, space);
-            JAMI_INFO() << "p.window_id.empty()";
             auto splits = jami::split_string_to_unsigned(display.substr(space + 1), 'x');
             // round to 8 pixel block
             p.width = round2pow(splits[0], 3);
@@ -469,31 +468,61 @@ VideoInput::initAVFoundation(const std::string& display)
     return true;
 }
 
+#ifdef WIN32
 bool
-VideoInput::initGdiGrab(const std::string& params)
+VideoInput::initWindowsGrab(const std::string& display)
 {
-    size_t space = params.find(' ');
-    clearOptions();
-    decOpts_ = jami::getVideoDeviceMonitor().getDeviceParams(DEVICE_DESKTOP);
-
-    if (space != std::string::npos) {
-        std::istringstream iss(params.substr(space + 1));
-        char sep;
-        unsigned w, h;
-        iss >> w >> sep >> h;
-        decOpts_.width = round2pow(w, 3);
-        decOpts_.height = round2pow(h, 3);
+    // Patterns
+    // full screen sharing : :1+0,0 2560x1440 - SCREEN 1, POSITION 0X0, RESOLUTION 2560X1440
+    // area sharing : :1+882,211 1532x779 - SCREEN 1, POSITION 882x211, RESOLUTION 1532x779
+    // window sharing : :+1,0 0x0 window-id:TITLE - POSITION 0X0
+    size_t space = display.find(' ');
+    std::string windowIdStr = "window-id:";
+    size_t winIdPos = display.find(windowIdStr);
 
-        size_t plus = params.find('+');
-        std::istringstream dss(params.substr(plus + 1, space - plus));
-        dss >> decOpts_.offset_x >> sep >> decOpts_.offset_y;
+    DeviceParams p = jami::getVideoDeviceMonitor().getDeviceParams(DEVICE_DESKTOP);
+    if (winIdPos != std::string::npos) {
+        p.input = display.substr(winIdPos + windowIdStr.size()); // "TITLE";
+        p.name  = display.substr(winIdPos + windowIdStr.size()); // "TITLE";
+        p.is_area = 0;
     } else {
-        decOpts_.width = default_grab_width;
-        decOpts_.height = default_grab_height;
+        p.input = display.substr(1);
+        p.name = display.substr(1);
+        p.is_area = 1;
+        if (space != std::string::npos) {
+            auto splits = jami::split_string_to_unsigned(display.substr(space + 1), 'x');
+            if (splits.size() != 2)
+                return false;
+
+            // round to 8 pixel block
+            p.width = splits[0];
+            p.height = splits[1];
+
+            size_t plus = display.find('+');
+            auto position = display.substr(plus + 1, space - plus - 1);
+            splits = jami::split_string_to_unsigned(position, ',');
+            if (splits.size() != 2)
+                return false;
+            p.offset_x = splits[0];
+            p.offset_y = splits[1];
+        } else {
+            p.width = default_grab_width;
+            p.height = default_grab_height;
+        }
     }
 
+    auto dec = std::make_unique<MediaDecoder>();
+    if (dec->openInput(p) < 0 || dec->setupVideo() < 0)
+        return initCamera(jami::getVideoDeviceMonitor().getDefaultDevice());
+
+    clearOptions();
+    decOpts_ = p;
+    decOpts_.width = dec->getStream().width;
+    decOpts_.height = dec->getStream().height;
+
     return true;
 }
+#endif
 
 bool
 VideoInput::initFile(std::string path)
@@ -588,8 +617,8 @@ VideoInput::switchInput(const std::string& resource)
         /* X11 display name */
 #ifdef __APPLE__
         ready = initAVFoundation(suffix);
-#elif defined(_WIN32)
-        ready = initGdiGrab(suffix);
+#elif defined(WIN32)
+        ready = initWindowsGrab(suffix);
 #else
         ready = initX11(suffix);
 #endif
diff --git a/src/media/video/video_input.h b/src/media/video/video_input.h
index f8a27eb37e02b08ffb7facee755e2e5ef4f989aa..570427ec9d275d06fa68e3a6a6d69013a863b0d3 100644
--- a/src/media/video/video_input.h
+++ b/src/media/video/video_input.h
@@ -135,7 +135,9 @@ private:
     bool initX11(const std::string& display);
     bool initAVFoundation(const std::string& display);
     bool initFile(std::string path);
-    bool initGdiGrab(const std::string& params);
+#ifdef WIN32
+    bool initWindowsGrab(const std::string& display);
+#endif
 
     bool isCapturing() const noexcept;
     void startLoop();
diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp
index c3a0d46cd2f7d97c933abbea290797db3be89f0e..8dbe3114efaea879774764b04773ef28cbd5c67f 100644
--- a/src/media/video/video_rtp_session.cpp
+++ b/src/media/video/video_rtp_session.cpp
@@ -166,7 +166,7 @@ VideoRtpSession::startSender()
         // Current implementation does not handle resolution change
         // (needed by window sharing feature) with HW codecs, so HW
         // codecs will be disabled for now.
-        bool allowHwAccel = (localVideoParams_.format != "x11grab");
+        bool allowHwAccel = (localVideoParams_.format != "x11grab" && localVideoParams_.format != "dxgigrab");
 
         if (socketPair_)
             initSeqVal_ = socketPair_->lastSeqValOut();
diff --git a/src/media/video/winvideo/video_device_impl.cpp b/src/media/video/winvideo/video_device_impl.cpp
index adb752423ba8d925a6e8e158308d0df312941eaf..11d8e9a57842d47b36a4660d60a70433396b0f84 100644
--- a/src/media/video/winvideo/video_device_impl.cpp
+++ b/src/media/video/winvideo/video_device_impl.cpp
@@ -281,7 +281,7 @@ VideoDeviceImpl::getDeviceParams() const
     params.unique_id = id;
     params.input = id;
     if (id == DEVICE_DESKTOP) {
-        params.format = "gdigrab";
+        params.format = "dxgigrab";
         params.framerate = desktopFrameRate_;
         return params;
     }