diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11desktopdupsrc.cpp b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11desktopdupsrc.cpp new file mode 100644 index 0000000000..3aac3ce5b0 --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11desktopdupsrc.cpp @@ -0,0 +1,215 @@ +/* GStreamer + * Copyright (C) 2021 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static GstDevice * +enum_devices (gboolean only_show, gint monitor_idx, guint64 monitor_handle) +{ + GstDeviceMonitor *monitor; + GstCaps *caps; + GList *devices, *iter; + gboolean ret; + guint i; + GstDevice *target = nullptr; + + monitor = gst_device_monitor_new (); + + /* Filtering by using d3d11 memory caps with "Source/Monitor" class */ + caps = gst_caps_from_string ("video/x-raw(memory:D3D11Memory)"); + ret = gst_device_monitor_add_filter (monitor, "Source/Monitor", caps); + gst_caps_unref (caps); + + if (!ret) { + gst_object_unref (monitor); + g_warning ("Failed to setup device monitor"); + return nullptr; + } + + gst_device_monitor_start (monitor); + devices = gst_device_monitor_get_devices (monitor); + + if (!devices) { + g_warning ("No detected d3d11 monitor device"); + gst_device_monitor_stop (monitor); + gst_object_unref (monitor); + return nullptr; + } + + gst_println ("Found %d monitor device(s)", g_list_length (devices)); + + for (iter = devices, i = 0; iter; iter = g_list_next (iter), i++) { + GstDevice *dev = GST_DEVICE (iter->data); + GstStructure *s; + guint disp_coord_left, disp_coord_top, disp_coord_right, disp_coord_bottom; + gchar *name = nullptr; + gchar *adapter_desc = nullptr; + guint64 hmonitor; + HMONITOR handle; + gboolean primary; + + s = gst_device_get_properties (dev); + + gst_structure_get (s, + "display.coordinates.left", G_TYPE_INT, &disp_coord_left, + "display.coordinates.top", G_TYPE_INT, &disp_coord_top, + "display.coordinates.right", G_TYPE_INT, &disp_coord_right, + "display.coordinates.bottom", G_TYPE_INT, &disp_coord_bottom, + "device.adapter.description", G_TYPE_STRING, &adapter_desc, + "device.hmonitor", G_TYPE_UINT64, &hmonitor, + "device.primary", G_TYPE_BOOLEAN, &primary, nullptr); + + name = gst_device_get_display_name (dev); + + handle = (HMONITOR) hmonitor; + + gst_println ("Monitor %d (%s - %s):", i, name, adapter_desc); + gst_println (" HMONITOR: %p (%" G_GUINT64_FORMAT ")", handle, hmonitor); + gst_println (" Display Coordinates (left:top:right:bottom): %d:%d:%d:%d\n", + disp_coord_left, disp_coord_top, disp_coord_right, disp_coord_bottom); + + g_free (adapter_desc); + g_free (name); + + if (!only_show && !target) { + if (monitor_handle != 0) { + if (monitor_handle == hmonitor) { + target = (GstDevice *) gst_object_ref (dev); + } + } else if (monitor_idx < 0) { + if (primary) { + target = (GstDevice *) gst_object_ref (dev); + } + } else if (monitor_idx == i) { + target = (GstDevice *) gst_object_ref (dev); + } + + if (target) + gst_println ("Found target monitor device"); + } + } + g_list_free_full (devices, gst_object_unref); + + return target; +} + +static gboolean +bus_msg (GstBus * bus, GstMessage * msg, GMainLoop * loop) +{ + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *dbg; + + gst_message_parse_error (msg, &err, &dbg); + g_printerr ("ERROR %s \n", err->message); + if (dbg != NULL) + g_printerr ("ERROR debug information: %s\n", dbg); + g_clear_error (&err); + g_free (dbg); + + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + +gint +main (gint argc, gchar ** argv) +{ + GstElement *pipeline, *src, *queue, *sink; + GMainLoop *loop; + gboolean ret; + gboolean show_devices = FALSE; + gint64 hmonitor = 0; + gint monitor_index = -1; + GError *err = nullptr; + GstDevice *device; + GOptionContext *option_ctx; + GOptionEntry options[] = { + {"show-devices", 0, 0, G_OPTION_ARG_NONE, &show_devices, + "Display available monitor devices", nullptr}, + {"hmonitor", 0, 0, G_OPTION_ARG_INT64, &hmonitor, + "Address of HMONITOR handle", nullptr}, + {"index", 0, 0, G_OPTION_ARG_INT, &monitor_index, + "Monitor index to capture (-1 for primary monitor)", nullptr}, + {nullptr} + }; + + option_ctx = g_option_context_new ("D3D11 desktop capture example"); + g_option_context_add_main_entries (option_ctx, options, NULL); + g_option_context_add_group (option_ctx, gst_init_get_option_group ()); + ret = g_option_context_parse (option_ctx, &argc, &argv, &err); + g_option_context_free (option_ctx); + + if (!ret) { + g_printerr ("option parsing failed: %s\n", err->message); + g_clear_error (&err); + return 1; + } + + device = enum_devices (show_devices, monitor_index, (guint64) hmonitor); + if (show_devices) { + gst_clear_object (&device); + return 0; + } + + if (!device) { + gst_println ("Failed to find monitor device"); + return 1; + } + + src = gst_device_create_element (device, nullptr); + gst_object_unref (device); + if (!src) { + g_warning ("Failed to create d3d11desktopdup element"); + return 1; + } + + loop = g_main_loop_new (nullptr, FALSE); + pipeline = gst_pipeline_new (nullptr); + + queue = gst_element_factory_make ("queue", nullptr); + sink = gst_element_factory_make ("d3d11videosink", nullptr); + + gst_bin_add_many (GST_BIN (pipeline), src, queue, sink, nullptr); + gst_element_link_many (src, queue, sink, nullptr); + + gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), (GstBusFunc) bus_msg, loop); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_bus_remove_watch (GST_ELEMENT_BUS (pipeline)); + + gst_object_unref (pipeline); + g_main_loop_unref (loop); + + return 0; +} diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11device.cpp b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11device.cpp similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11device.cpp rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11device.cpp diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11device.h b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11device.h similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11device.h rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11device.h diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-kb.c b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-kb.c similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-kb.c rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-kb.c diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-kb.h b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-kb.h similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-kb.h rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-kb.h diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-shared-texture-d3d9ex.cpp b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-shared-texture-d3d9ex.cpp similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-shared-texture-d3d9ex.cpp rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-shared-texture-d3d9ex.cpp diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-shared-texture.cpp b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-shared-texture.cpp similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink-shared-texture.cpp rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-shared-texture.cpp diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink.c b/subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink.c similarity index 100% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/d3d11videosink.c rename to subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink.c diff --git a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/meson.build b/subprojects/gst-plugins-bad/tests/examples/d3d11/meson.build similarity index 87% rename from subprojects/gst-plugins-bad/tests/examples/d3d11videosink/meson.build rename to subprojects/gst-plugins-bad/tests/examples/d3d11/meson.build index 377c7513eb..12e73695c8 100644 --- a/subprojects/gst-plugins-bad/tests/examples/d3d11videosink/meson.build +++ b/subprojects/gst-plugins-bad/tests/examples/d3d11/meson.build @@ -7,6 +7,14 @@ if host_system == 'windows' install: false, ) + executable('d3d11desktopdupsrc', + ['d3d11desktopdupsrc.cpp'], + c_args : gst_plugins_bad_args, + include_directories : [configinc, libsinc], + dependencies: [gst_dep, gstbase_dep, gstvideo_dep], + install: false, + ) + d3d11_lib = cc.find_library('d3d11', required : false) dxgi_lib = cc.find_library('dxgi', required : false) d3dcompiler_lib = cc.find_library('d3dcompiler', required: false) diff --git a/subprojects/gst-plugins-bad/tests/examples/meson.build b/subprojects/gst-plugins-bad/tests/examples/meson.build index 802d2b6283..7a2057e7b8 100644 --- a/subprojects/gst-plugins-bad/tests/examples/meson.build +++ b/subprojects/gst-plugins-bad/tests/examples/meson.build @@ -2,7 +2,7 @@ subdir('audiomixmatrix') subdir('avsamplesink') subdir('camerabin2') subdir('codecparsers') -subdir('d3d11videosink') +subdir('d3d11') subdir('directfb') subdir('ipcpipeline') subdir('mpegts')