Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
@ 2023-02-09 14:22 aline.gondimsantos
  2023-02-09 15:58 ` Timo Rothenpieler
  0 siblings, 1 reply; 6+ messages in thread
From: aline.gondimsantos @ 2023-02-09 14:22 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Aline Gondim Santos

From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>

A dxgi grab device may be either a display or a window.
Differently from the existing gdigrab, this new device does
not make the mouse to flick and also allows proper grabbing of
accelerated windows, such as chrome or visual studio code.

Signed-off-by: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
---
 configure                        |   1 +
 libavdevice/Makefile             |   4 +
 libavdevice/alldevices.c         |   1 +
 libavdevice/d3dHelpers.h         |  59 ++++++++
 libavdevice/direct3d11.interop.h |  51 +++++++
 libavdevice/dxgigrab.cpp         | 225 +++++++++++++++++++++++++++++++
 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, 847 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 12184c7f26..c9cbee0c09 100755
--- a/configure
+++ b/configure
@@ -3529,6 +3529,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"
 iec61883_indev_select="dv_demuxer"
 jack_indev_deps="libjack"
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index 8a62822b69..6740012000 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -30,6 +30,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
@@ -72,5 +73,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..9774e72ab1
--- /dev/null
+++ b/libavdevice/dxgigrab.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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"
+
+#include <dwmapi.h>
+#include <sstream>
+
+#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;
+    std::string handle;
+    AVStream   *st       = NULL;
+
+    if (!strncmp(s1->url, "hwnd=", 5)) {
+        if (!s->hwnd) {
+            handle = s1->url + 5;
+            try {
+                s->hwnd = reinterpret_cast<HWND>(std::stoull(handle, nullptr, 16));
+            } catch (...) {}
+            if (!s->hwnd) {
+                av_log(s1, AV_LOG_ERROR,
+                       "Can't find window from handle '%s', aborting.\n", handle.c_str());
+                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 \"hwnd=<windowHandle>\" 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 \"hwnd=<windowHandle>\" 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 = handle;
+        x_internal->windowHandle = handle;
+    }
+
+    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..92cad7dab8
--- /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 windowHandle;
+    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..c6b29f1a1d
--- /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 false;
+    auto shouldResize = false;
+
+    auto frame = m_framePool.TryGetNextFrame();
+    if (!frame)
+        return false;
+
+    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 false;
+
+    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 true;
+}
+
+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.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
  2023-02-09 14:22 [FFmpeg-devel] [PATCH] avdevice: add dxgigrab aline.gondimsantos
@ 2023-02-09 15:58 ` Timo Rothenpieler
  2023-02-09 16:10   ` Nicolas George
                     ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Timo Rothenpieler @ 2023-02-09 15:58 UTC (permalink / raw)
  To: ffmpeg-devel

On 09.02.2023 15:22, aline.gondimsantos@savoirfairelinux.com wrote:
> From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
> 
> A dxgi grab device may be either a display or a window.
> Differently from the existing gdigrab, this new device does
> not make the mouse to flick and also allows proper grabbing of
> accelerated windows, such as chrome or visual studio code.

How do you get access to the d3d hwdevice, given this lives in lavd, 
which has no provisions for that?
This looks much more like it'd fit in with the desktop duplication 
capture, which ended up being a vsrc filter for that reason.

> Signed-off-by: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
> ---
>   configure                        |   1 +
>   libavdevice/Makefile             |   4 +
>   libavdevice/alldevices.c         |   1 +
>   libavdevice/d3dHelpers.h         |  59 ++++++++
>   libavdevice/direct3d11.interop.h |  51 +++++++
>   libavdevice/dxgigrab.cpp         | 225 +++++++++++++++++++++++++++++++
>   libavdevice/dxgigrab.h           |  83 ++++++++++++
>   libavdevice/dxgigrab_c.c         |  59 ++++++++
>   libavdevice/dxgigrab_c.h         |  98 ++++++++++++++
>   libavdevice/windows_capture.cpp  | 184 +++++++++++++++++++++++++
>   libavdevice/windows_capture.h    |  82 +++++++++++

The name of these files seem way too generic to just sit there like this 
in the top level.

>   11 files changed, 847 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 12184c7f26..c9cbee0c09 100755
> --- a/configure
> +++ b/configure
> @@ -3529,6 +3529,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"
>   iec61883_indev_select="dv_demuxer"
>   jack_indev_deps="libjack"
> diff --git a/libavdevice/Makefile b/libavdevice/Makefile
> index 8a62822b69..6740012000 100644
> --- a/libavdevice/Makefile
> +++ b/libavdevice/Makefile
> @@ -30,6 +30,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
> @@ -72,5 +73,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>

Are these headers parts of any normal windows SDK?
I don't see them in anything mingw has.
Does this break cross compiling from Linux, or with anything that's not 
MSVC?

And given it's winrt... does this work on normal Desktop Windows?
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
  2023-02-09 15:58 ` Timo Rothenpieler
@ 2023-02-09 16:10   ` Nicolas George
  2023-02-09 16:38     ` Timo Rothenpieler
  2023-02-09 19:01   ` Aline Gondim Santos Gondim Santos
  2023-02-09 22:00   ` Michael Niedermayer
  2 siblings, 1 reply; 6+ messages in thread
From: Nicolas George @ 2023-02-09 16:10 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Timo Rothenpieler (12023-02-09):
> How do you get access to the d3d hwdevice, given this lives in lavd, which
> has no provisions for that?

Would it work better if it was in the same library?

Regards,

-- 
  Nicolas George
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
  2023-02-09 16:10   ` Nicolas George
@ 2023-02-09 16:38     ` Timo Rothenpieler
  0 siblings, 0 replies; 6+ messages in thread
From: Timo Rothenpieler @ 2023-02-09 16:38 UTC (permalink / raw)
  To: ffmpeg-devel

On 09.02.2023 17:10, Nicolas George wrote:
> Timo Rothenpieler (12023-02-09):
>> How do you get access to the d3d hwdevice, given this lives in lavd, which
>> has no provisions for that?
> 
> Would it work better if it was in the same library?

It's not so much about in which library it is, but that there is 
absolutely no API for hwdecide stuff in lavd.
While lavfi is all prepared for it, and ffmpeg.c has tons of options to 
control it.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
  2023-02-09 15:58 ` Timo Rothenpieler
  2023-02-09 16:10   ` Nicolas George
@ 2023-02-09 19:01   ` Aline Gondim Santos Gondim Santos
  2023-02-09 22:00   ` Michael Niedermayer
  2 siblings, 0 replies; 6+ messages in thread
From: Aline Gondim Santos Gondim Santos @ 2023-02-09 19:01 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

> How do you get access to the d3d hwdevice, given this lives in lavd,
> which has no provisions for that?
> This looks much more like it'd fit in with the desktop duplication
> capture, which ended up being a vsrc filter for that reason.

Upon developing the device i did notice the d3dhwdevice but I do not use it to get the frames.
When it was written that we could access accelerated windows, I did not mean to say that the
output from dxgigrab is an accelerated format. The access to such window frames is due to the
API that allows us to map the frames for CPU access.


> The name of these files seem way too generic to just sit there like this
> in the top level.

I can either rename or rearrange the files to a sub-folder is the patch is to be accepted.

> Are these headers parts of any normal windows SDK?
> I don't see them in anything mingw has.
> Does this break cross compiling from Linux, or with anything that's not
> MSVC?
> And given it's winrt... does this work on normal Desktop Windows?

Build was tested from a normal Windows 10 Desktop with both VisualStudio 2019 and 2022, the required SDK is 10.0.18632.0.
lower SDK do not have required includes and SDK 10.019XXX is bugged. Other SDKs were not tested.
In the following link you can find the configuration used to build. https://git.jami.net/savoirfairelinux/jami-daemon/-/blob/master/contrib/src/ffmpeg/windows-configure-make.sh
please consider $1 = win32 and $2 = x64 .


For note, the current Jami beta release (https://jami.net/download-jami-windows/) uses the patch for window sharing in calls.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [FFmpeg-devel] [PATCH] avdevice: add dxgigrab
  2023-02-09 15:58 ` Timo Rothenpieler
  2023-02-09 16:10   ` Nicolas George
  2023-02-09 19:01   ` Aline Gondim Santos Gondim Santos
@ 2023-02-09 22:00   ` Michael Niedermayer
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Niedermayer @ 2023-02-09 22:00 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 7154 bytes --]

On Thu, Feb 09, 2023 at 04:58:46PM +0100, Timo Rothenpieler wrote:
> On 09.02.2023 15:22, aline.gondimsantos@savoirfairelinux.com wrote:
> > From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
> > 
> > A dxgi grab device may be either a display or a window.
> > Differently from the existing gdigrab, this new device does
> > not make the mouse to flick and also allows proper grabbing of
> > accelerated windows, such as chrome or visual studio code.
> 
> How do you get access to the d3d hwdevice, given this lives in lavd, which
> has no provisions for that?
> This looks much more like it'd fit in with the desktop duplication capture,
> which ended up being a vsrc filter for that reason.
> 
> > Signed-off-by: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
> > ---
> >   configure                        |   1 +
> >   libavdevice/Makefile             |   4 +
> >   libavdevice/alldevices.c         |   1 +
> >   libavdevice/d3dHelpers.h         |  59 ++++++++
> >   libavdevice/direct3d11.interop.h |  51 +++++++
> >   libavdevice/dxgigrab.cpp         | 225 +++++++++++++++++++++++++++++++
> >   libavdevice/dxgigrab.h           |  83 ++++++++++++
> >   libavdevice/dxgigrab_c.c         |  59 ++++++++
> >   libavdevice/dxgigrab_c.h         |  98 ++++++++++++++
> >   libavdevice/windows_capture.cpp  | 184 +++++++++++++++++++++++++
> >   libavdevice/windows_capture.h    |  82 +++++++++++
> 
> The name of these files seem way too generic to just sit there like this in
> the top level.
> 
> >   11 files changed, 847 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 12184c7f26..c9cbee0c09 100755
> > --- a/configure
> > +++ b/configure
> > @@ -3529,6 +3529,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"
> >   iec61883_indev_select="dv_demuxer"
> >   jack_indev_deps="libjack"
> > diff --git a/libavdevice/Makefile b/libavdevice/Makefile
> > index 8a62822b69..6740012000 100644
> > --- a/libavdevice/Makefile
> > +++ b/libavdevice/Makefile
> > @@ -30,6 +30,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
> > @@ -72,5 +73,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>
> 
> Are these headers parts of any normal windows SDK?
> I don't see them in anything mingw has.
> Does this break cross compiling from Linux, or with anything that's not
> MSVC?

not just cross compile, this patch breaks normal build on linux

make
CXX	libavdevice/dxgigrab.o
cc1plus: warning: command line option ‘-Wdeclaration-after-statement’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wmissing-prototypes’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
cc1plus: warning: command line option ‘-Wno-pointer-sign’ is valid for C/ObjC but not for C++
cc1plus: warning: ‘-Werror=’ argument ‘-Werror=implicit-function-declaration’ is not valid for C++
cc1plus: warning: ‘-Werror=’ argument ‘-Werror=missing-prototypes’ is not valid for C++
cc1plus: warning: command line option ‘-std=c11’ is valid for C/ObjC but not for C++
In file included from libavdevice/dxgigrab.h:37:0,
                 from libavdevice/dxgigrab.cpp:29:
libavdevice/dxgigrab_c.h:43:10: fatal error: windows.h: No such file or directory
 #include <windows.h>
          ^~~~~~~~~~~
compilation terminated.
ffbuild/common.mak:84: recipe for target 'libavdevice/dxgigrab.o' failed
make: *** [libavdevice/dxgigrab.o] Error 1

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

There will always be a question for which you do not know the correct answer.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-02-09 22:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-09 14:22 [FFmpeg-devel] [PATCH] avdevice: add dxgigrab aline.gondimsantos
2023-02-09 15:58 ` Timo Rothenpieler
2023-02-09 16:10   ` Nicolas George
2023-02-09 16:38     ` Timo Rothenpieler
2023-02-09 19:01   ` Aline Gondim Santos Gondim Santos
2023-02-09 22:00   ` Michael Niedermayer

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git