1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-11-23 21:54:53 +02:00

avfilter: add gfxcapture, Windows.Graphics.Capture based window/monitor capture

This commit is contained in:
Timo Rothenpieler
2025-08-30 00:45:22 +02:00
parent 7856f57533
commit 36e374efb0
11 changed files with 2220 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
version <next>:
- ffprobe -codec option
- EXIF Metadata Parsing
- gfxcapture: Windows.Graphics.Capture based window/monitor capture
version 8.0:

8
configure vendored
View File

@@ -2516,6 +2516,8 @@ TOOLCHAIN_FEATURES="
TYPES_LIST="
DPI_AWARENESS_CONTEXT
IDXGIOutput5
__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession5
IDirect3DDxgiInterfaceAccess
kCMVideoCodecType_HEVC
kCMVideoCodecType_HEVCWithAlpha
kCMVideoCodecType_VP9
@@ -3412,6 +3414,8 @@ pad_cuda_filter_deps_any="cuda_nvcc cuda_llvm"
sharpen_npp_filter_deps="ffnvcodec libnpp"
ddagrab_filter_deps="d3d11va IDXGIOutput1 DXGI_OUTDUPL_FRAME_INFO"
gfxcapture_filter_deps="cxx17 threads d3d11va IGraphicsCaptureItemInterop __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession3"
gfxcapture_filter_extralibs="-lstdc++"
scale_d3d11_filter_deps="d3d11va"
amf_deps_any="libdl LoadLibrary"
@@ -6940,6 +6944,10 @@ check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00
check_type "windows.h security.h schnlsp.h" SecPkgContext_KeyingMaterialInfo -DSECURITY_WIN32
check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602
check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat
check_type "windows.h windows.graphics.capture.h" __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession3 -D_WIN32_WINNT=0x0A00 -DWINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION=0x130000 -DCOBJMACROS
check_type "windows.h windows.graphics.capture.h" __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession5 -D_WIN32_WINNT=0x0A00 -DWINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION=0x130000 -DCOBJMACROS
check_type "windows.h windows.graphics.capture.interop.h" IGraphicsCaptureItemInterop -D_WIN32_WINNT=0x0A00 -DWINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION=0x130000 -DCOBJMACROS
check_type "windows.h windows.graphics.directx.direct3d11.interop.h" IDirect3DDxgiInterfaceAccess -D_WIN32_WINNT=0x0A00 -DWINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION=0x130000 -DCOBJMACROS
check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
check_type "vdpau/vdpau.h" "VdpPictureInfoVP9"

View File

@@ -29614,6 +29614,165 @@ ddagrab=video_size=800x600:offset_x=100:offset_y=100
@end example
@section gfxcapture
Capture windows or monitors using Windows.Graphics.Capture API.
This source provides low overhead capture of application windows or entire monitors.
The filter outputs hardware frames in @code{d3d11} format; use @code{hwdownload,format=}
if system memory frames are required.
The window to be captured can be selected via regular expressions on its title,
class name or backing executable name, by explicit native handles, or by monitor
index or explicit native handle. A window must match all provided expressions to be
selected. The first matching window will be picked, in whatever order Windows
returns them.
Explicit handles (@option{hwnd}, @option{hmonitor}) override pattern or index
based selection. If neither handles nor a monitor index are given, the first
window matching the provided regular expressions is captured.
This source does NOT hold a stable FPS. It returns frames at whatever rate the compositor
provides them, only capped by the @option{max_framerate}.
If you need a stable rate, you need to add an fps filter to drop/duplicate frames as needed.
If the capture source disappears mid-capture (window closed, monitor disconnected), the filter will return EOF.
This source accepts the following options:
@table @option
@item window_title
ECMAScript regular expression matched against the window title. Supports a
PCRE style @code{(?i)} prefix for case-insensitive matching.
@item window_class
As @option{window_title}, but matched against the window class name.
@item window_exe
As @option{window_title}, but matched against the executable file name of the
window's process.
@item monitor_idx
Zero-based index of the monitor to capture.
Can also be set to @code{window} to capture the monitor the selected window
is displayed on at filter initialization time.
@item hwnd
Explicit native window handle (HWND).
@item hmonitor
Explicit native monitor handle (HMONITOR).
@item capture_cursor
Capture the mouse cursor. Enabled by default.
@item capture_border
Capture the full area of the window, including its window decorarions/border.
Disabled by default.
@item display_border
Draw a yellow highlight border around the captured window. Disabled by default.
@item max_framerate
Maximum capture frame rate. Accepts a video rate (e.g. @code{30}, @code{60/1},
@code{24000/1001}). The default is @code{60} FPS.
The actual rate is the rate at which the compositor renders the window/monitor,
capped by this option.
@item width
Force the output canvas width. If zero (default) the initial captured source
width is used. If a negative number is provided, the width will be rounded
down to the next multiple of that number.
See @option{resize_mode}.
@item height
Force the output canvas height. If zero (default) the initial captured source
height is used. If a negative number is provided, the height will be rounded
down to the next multiple of that number.
See @option{resize_mode}.
@item crop_left
Crop this many pixels from the left side of the captured frames.
@item crop_top
Crop this many pixels from the left side of the captured frames.
@item crop_right
Crop this many pixels from the left side of the captured frames.
@item crop_bottom
Crop this many pixels from the left side of the captured frames.
@item premultiplied
If set to 1, return frames with premultiplied alpha. Default is 0 (straight
alpha).
@item resize_mode
Defines how the captured content is fitted into the output canvas size.
Possible values:
@table @samp
@item crop
Crop (or pad with black) to the canvas size. (default)
@item scale
Scale the source to fill the canvas, potentially altering aspect ratio.
@item scale_aspect
Scale the source to fit inside the canvas while preserving aspect ratio.
Remaining area is filled with black.
@end table
@item scale_mode
Scaling algorithm used when resizing is required.
Possible values:
@table @samp
@item point
Nearest neighbour (pixelated) scaling.
@item bilinear
Bilinear filtering. (default)
@item bicubic
Bicubic filtering. Potentially more blurry, but fewer scaling artifacts depending on contents.
@end table
@item output_fmt
Desired output pixel format inside the D3D11 hardware frames.
Possible values:
@table @samp
@item bgra
@item 8bit
8 bit BGRA output (default)
@item x2bgr10
@item 10bit
10 bit BGR output
@item rgbaf16
@item 16bit
16bit float RGBA output
@end table
@end table
@subsection Examples
@itemize
@item Capture a window by title (case-insensitive) at a maximum of 60 fps:
@example
ffmpeg -filter_complex gfxcapture=window_text='(?i)My Application':max_framerate=60,hwdownload,format=bgra,format=yuv420p -c:v libx264 -crf 15 capture.mp4
@end example
@item Capture monitor 1 at native refresh, 10bit color depth, scale to 1920x1080 preserving aspect:
@example
ffmpeg -filter_complex gfxcapture=monitor_idx=1:width=1920:height=1080:resize_mode=scale_aspect:output_fmt=10bit -c:v hevc_nvenc -cq 15 capture.mp4
@end example
@item Capture a window by executable name, draw border, force point scaling, fixed 60 fps:
@example
ffmpeg -filter_complex gfxcapture=window_exe='^firefox.exe$':display_border=1:scale_mode=point,fps=60 -rc qvbr -qvbr_quality_level 15 -c:v h264_amf capture.mp4
@end example
@end itemize
@section gradients
Generate several gradients.

View File

@@ -609,6 +609,7 @@ OBJS-$(CONFIG_COLORSPECTRUM_FILTER) += vsrc_testsrc.o
OBJS-$(CONFIG_COREIMAGESRC_FILTER) += vf_coreimage.o
OBJS-$(CONFIG_DDAGRAB_FILTER) += vsrc_ddagrab.o
OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o
OBJS-$(CONFIG_GFXCAPTURE_FILTER) += vsrc_gfxcapture.o vsrc_gfxcapture_winrt.o
OBJS-$(CONFIG_GRADIENTS_FILTER) += vsrc_gradients.o
OBJS-$(CONFIG_HALDCLUTSRC_FILTER) += vsrc_testsrc.o
OBJS-$(CONFIG_LIFE_FILTER) += vsrc_life.o

View File

@@ -571,6 +571,7 @@ extern const FFFilter ff_vsrc_colorspectrum;
extern const FFFilter ff_vsrc_coreimagesrc;
extern const FFFilter ff_vsrc_ddagrab;
extern const FFFilter ff_vsrc_frei0r_src;
extern const FFFilter ff_vsrc_gfxcapture;
extern const FFFilter ff_vsrc_gradients;
extern const FFFilter ff_vsrc_haldclutsrc;
extern const FFFilter ff_vsrc_life;

View File

@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVFILTER_VERSION_MINOR 8
#define LIBAVFILTER_VERSION_MINOR 9
#define LIBAVFILTER_VERSION_MICRO 100

View File

@@ -0,0 +1,102 @@
/*
* 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
*/
#include "config.h"
#include "libavutil/internal.h"
#include "libavutil/opt.h"
#include "avfilter.h"
#include "filters.h"
#include "vsrc_gfxcapture.h"
#define OFFSET(x) offsetof(GfxCaptureContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static const AVOption gfxcapture_options[] = {
{ "window_title", "ECMAScript regular expression to match against the window title. "
"Supports PCRE style (?i) prefix for case-insensitivity.",
OFFSET(window_text), AV_OPT_TYPE_STRING, { .str = NULL }, 0, INT_MAX, FLAGS },
{ "window_class", "as window_title, but against the window class",
OFFSET(window_class), AV_OPT_TYPE_STRING, { .str = NULL }, 0, INT_MAX, FLAGS },
{ "window_exe", "as window_title, but against the windows executable name",
OFFSET(window_exe), AV_OPT_TYPE_STRING, { .str = NULL }, 0, INT_MAX, FLAGS },
{ "monitor_idx", "index of the monitor to capture", OFFSET(monitor_idx), AV_OPT_TYPE_INT, { .i64 = GFX_MONITOR_IDX_DEFAULT }, GFX_MONITOR_IDX_DEFAULT, INT_MAX, FLAGS, .unit = "monitor_idx" },
{ "window", "derive from selected window", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_MONITOR_IDX_WINDOW }, 0, 0, FLAGS, .unit = "monitor_idx" },
{ "capture_cursor", "capture mouse cursor", OFFSET(capture_cursor), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
{ "capture_border", "capture full window border", OFFSET(capture_border), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
{ "display_border", "display yellow border around captured window",
OFFSET(display_border), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
{ "max_framerate", "set maximum capture frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "60" }, 0.001, 1000, FLAGS },
{ "hwnd", "pre-existing HWND handle", OFFSET(user_hwnd), AV_OPT_TYPE_UINT64, { .i64 = 0 }, 0, UINT64_MAX, FLAGS },
{ "hmonitor", "pre-existing HMONITOR handle", OFFSET(user_hmonitor), AV_OPT_TYPE_UINT64, { .i64 = 0 }, 0, UINT64_MAX, FLAGS },
{ "width", "force width of the output frames, negative values round down the width to the nearest multiple of that number",
OFFSET(canvas_width), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "height", "force height of the output frames, negative values round down the height to the nearest multiple of that number",
OFFSET(canvas_height), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "crop_left", "number of pixels to crop from the left of the captured area",
OFFSET(crop_left), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "crop_top", "number of pixels to crop from the top of the captured area",
OFFSET(crop_top), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "crop_right", "number of pixels to crop from the right of the captured area",
OFFSET(crop_right), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "crop_bottom", "number of pixels to crop from the bottom of the captured area",
OFFSET(crop_bottom), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "premultiplied", "return premultiplied alpha frames", OFFSET(premult_alpha), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
{ "resize_mode", "capture source resize behavior", OFFSET(resize_mode), AV_OPT_TYPE_INT, { .i64 = GFX_RESIZE_CROP }, 0, GFX_RESIZE_NB - 1, FLAGS, .unit = "resize_mode" },
{ "crop", "crop or add black bars into frame", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_RESIZE_CROP }, 0, 0, FLAGS, .unit = "resize_mode" },
{ "scale", "scale source to fit initial size", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_RESIZE_SCALE }, 0, 0, FLAGS, .unit = "resize_mode" },
{ "scale_aspect", "scale source to fit initial size while preserving aspect ratio",
0, AV_OPT_TYPE_CONST, { .i64 = GFX_RESIZE_SCALE_ASPECT }, 0, 0, FLAGS, .unit = "resize_mode" },
{ "scale_mode", "scaling algorithm", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = GFX_SCALE_BILINEAR }, 0, GFX_SCALE_NB - 1, FLAGS, .unit = "scale_mode" },
{ "point", "use point scaling", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_SCALE_POINT }, 0, 0, FLAGS, .unit = "scale_mode" },
{ "bilinear", "use bilinear scaling", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_SCALE_BILINEAR }, 0, 0, FLAGS, .unit = "scale_mode" },
{ "bicubic", "use bicubic scaling", 0, AV_OPT_TYPE_CONST, { .i64 = GFX_SCALE_BICUBIC }, 0, 0, FLAGS, .unit = "scale_mode" },
{ "output_fmt", "desired output format", OFFSET(out_fmt), AV_OPT_TYPE_INT, { .i64 = AV_PIX_FMT_BGRA }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
{ "8bit", "output default 8 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_BGRA }, 0, 0, FLAGS, .unit = "output_fmt" },
{ "bgra", "output 8 Bit BGRA", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_BGRA }, 0, 0, FLAGS, .unit = "output_fmt" },
{ "10bit", "output default 10 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_X2BGR10 }, 0, 0, FLAGS, .unit = "output_fmt" },
{ "x2bgr10", "output 10 Bit X2BGR10", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_X2BGR10 }, 0, 0, FLAGS, .unit = "output_fmt" },
{ "16bit", "output default 16 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_RGBAF16 }, 0, 0, FLAGS, .unit = "output_fmt" },
{ "rgbaf16", "output 16 Bit RGBAF16", 0, AV_OPT_TYPE_CONST, { .i64 = AV_PIX_FMT_RGBAF16 }, 0, 0, FLAGS, .unit = "output_fmt" },
{ NULL }
};
AVFILTER_DEFINE_CLASS(gfxcapture);
static const AVFilterPad gfxcapture_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = ff_gfxcapture_config_props,
},
};
const FFFilter ff_vsrc_gfxcapture = {
.p.name = "gfxcapture",
.p.description = NULL_IF_CONFIG_SMALL("Capture graphics/screen content as a video source"),
.p.priv_class = &gfxcapture_class,
.p.inputs = NULL,
.p.flags = AVFILTER_FLAG_HWDEVICE,
.priv_size = sizeof(GfxCaptureContext),
.init = ff_gfxcapture_init,
.uninit = ff_gfxcapture_uninit,
FILTER_OUTPUTS(gfxcapture_outputs),
FILTER_SINGLE_PIXFMT(AV_PIX_FMT_D3D11),
.flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
.activate = ff_gfxcapture_activate,
};

View File

@@ -0,0 +1,81 @@
/*
* 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
*/
#ifndef AVFILTER_VSRC_GFXCAPTURE_H
#define AVFILTER_VSRC_GFXCAPTURE_H
typedef struct GfxCaptureContextCpp GfxCaptureContextCpp;
enum GfxResizeMode {
GFX_RESIZE_CROP = 0,
GFX_RESIZE_SCALE,
GFX_RESIZE_SCALE_ASPECT,
GFX_RESIZE_NB
};
enum GfxScaleMode {
GFX_SCALE_POINT = 0,
GFX_SCALE_BILINEAR,
GFX_SCALE_BICUBIC,
GFX_SCALE_NB
};
enum GfxMonitorIdx {
GFX_MONITOR_IDX_WINDOW = -1,
GFX_MONITOR_IDX_DEFAULT = -2
};
typedef struct GfxCaptureContext {
const AVClass *avclass;
GfxCaptureContextCpp *ctx;
const char *window_text;
const char *window_class;
const char *window_exe;
int monitor_idx;
uint64_t user_hwnd;
uint64_t user_hmonitor;
int capture_cursor;
int capture_border;
int display_border;
AVRational frame_rate;
int canvas_width, canvas_height;
int crop_left, crop_top, crop_right, crop_bottom;
int out_fmt;
int resize_mode;
int scale_mode;
int premult_alpha;
} GfxCaptureContext;
#ifdef __cplusplus
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
av_cold int ff_gfxcapture_init(AVFilterContext *avctx) NOEXCEPT;
av_cold void ff_gfxcapture_uninit(AVFilterContext *avctx) NOEXCEPT;
int ff_gfxcapture_activate(AVFilterContext *avctx) NOEXCEPT;
int ff_gfxcapture_config_props(AVFilterLink *outlink) NOEXCEPT;
#undef NOEXCEPT
#endif /* AVFILTER_VSRC_GFXCAPTURE_H */

View File

@@ -0,0 +1,126 @@
/*
* 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
*/
#ifndef AVFILTER_VSRC_GFXCAPTURE_SHADER_H
#define AVFILTER_VSRC_GFXCAPTURE_SHADER_H
#define HLSL_SHADER(shader) #shader
static const char render_shader_src[] = HLSL_SHADER(
struct VSOut {
float4 pos : SV_Position;
float2 uv : TEXCOORD0;
};
cbuffer cb : register(b0) {
float2 tS;
float2 dS;
float2 uvMin;
float2 uvMax;
uint to_unpremult;
uint to_srgb;
uint2 pad;
};
Texture2D t0 : register(t0);
SamplerState s0 : register(s0);
VSOut main_vs(uint id : SV_VertexID) {
VSOut o;
o.pos = float4(id == 2 ? 3.0 : -1.0, id == 1 ? 3.0 : -1.0, 0, 1);
o.uv = lerp(uvMin, uvMax, float2((o.pos.x + 1) * 0.5, 1 - (o.pos.y + 1) * 0.5));
return o;
}
float4 cubic(float v) {
float4 n = float4(1.0, 2.0, 3.0, 4.0) - v;
float4 s = n * n * n;
float x = s.x;
float y = s.y - 4.0 * s.x;
float z = s.z - 4.0 * s.y + 6.0 * s.x;
float w = 6.0 - x - y - z;
return float4(x, y, z, w) * (1.0 / 6.0);
}
float4 texBicubic(Texture2D t, SamplerState ss, float2 uv) {
float2 itS = 1.0 / tS;
float2 tc = uv * tS - 0.5;
float2 fxy = frac(tc);
tc -= fxy;
float4 xc = cubic(fxy.x);
float4 yc = cubic(fxy.y);
float4 s = float4(xc.xz + xc.yw, yc.xz + yc.yw);
float4 o = tc.xxyy + (float2(-0.5, 1.5)).xyxy + float4(xc.yw, yc.yw) / s;
o *= itS.xxyy;
float4 s0 = t.Sample(ss, o.xz);
float4 s1 = t.Sample(ss, o.yz);
float4 s2 = t.Sample(ss, o.xw);
float4 s3 = t.Sample(ss, o.yw);
float sx = s.x / (s.x + s.y);
float sy = s.z / (s.z + s.w);
return lerp(lerp(s3, s2, sx), lerp(s1, s0, sx), sy);
}
float4 unpremultiply(float4 c) {
if (c.a < 1e-6)
return float4(0.0, 0.0, 0.0, 0.0);
return float4(c.rgb / c.a, c.a);
}
float4 premultiply(float4 c) {
return float4(c.rgb * c.a, c.a);
}
float3 linear_to_srgb(float3 c) {
c = max(c, 0.0);
float3 lo = 12.92 * c;
float3 hi = 1.055 * pow(c, 1.0 / 2.4) - 0.055;
return saturate(lerp(hi, lo, step(c, 0.0031308)));
}
float4 fix_color(float4 c) {
if (to_unpremult || to_srgb)
c = unpremultiply(c);
if (to_srgb) {
c.rgb = linear_to_srgb(c.rgb);
if (!to_unpremult)
c = premultiply(c);
}
return c;
}
float4 main_ps(VSOut i) : SV_Target {
return fix_color(t0.Sample(s0, i.uv));
}
float4 main_ps_bicubic(VSOut i) : SV_Target {
if (all(tS == dS))
return main_ps(i);
return fix_color(texBicubic(t0, s0, i.uv));
}
);
#undef HLSL_SHADER
#endif /* AVFILTER_VSRC_GFXCAPTURE_SHADER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,189 @@
/*
* 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
*/
#ifndef AVFILTER_VSRC_GFXCAPTURE_WINRT_H
#define AVFILTER_VSRC_GFXCAPTURE_WINRT_H
// Forward-declare IDirect3DDxgiInterfaceAccess if headers too old
#if !HAVE_IDIRECT3DDXGIINTERFACEACCESS
namespace Windows::Graphics::DirectX::Direct3D11 {
MIDL_INTERFACE("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1")
IDirect3DDxgiInterfaceAccess : public IUnknown
{
public:
IFACEMETHOD(GetInterface)(REFIID iid, _COM_Outptr_ void** p) = 0;
};
}
#ifdef __MINGW32__
__CRT_UUID_DECL(Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess,
0xa9b3d012, 0x3df2, 0x4ee3, 0xb8, 0xd1, 0x86, 0x95, 0xf4, 0x57, 0xd3, 0xc1)
#endif
#endif /* !HAVE_IDIRECT3DDXGIINTERFACEACCESS */
// Forward-declare IGraphicsCaptureSession5 if headers too old
#if !HAVE___X_ABI_CWINDOWS_CGRAPHICS_CCAPTURE_CIGRAPHICSCAPTURESESSION5
namespace ABI::Windows ::Graphics::Capture {
MIDL_INTERFACE("67C0EA62-1F85-5061-925A-239BE0AC09CB")
IGraphicsCaptureSession5 : public IInspectable
{
public:
IFACEMETHOD(get_MinUpdateInterval)(ABI::Windows::Foundation::TimeSpan* value) = 0;
IFACEMETHOD(put_MinUpdateInterval)(ABI::Windows::Foundation::TimeSpan value) = 0;
};
}
#ifdef __MINGW32__
__CRT_UUID_DECL(ABI::Windows ::Graphics::Capture::IGraphicsCaptureSession5,
0x67c0ea62, 0x1f85, 0x5061, 0x92, 0x5a, 0x23, 0x9b, 0xe0, 0xac, 0x09, 0xcb)
#endif
#endif /* !HAVE___X_ABI_CWINDOWS_CGRAPHICS_CCAPTURE_CIGRAPHICSCAPTURESESSION5 */
/****************************************************
* Helper class to implement refcounted COM objects *
****************************************************/
template<typename... Interfaces>
struct FFComObject : Interfaces...
{
virtual ~FFComObject() = default;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
{
if (!ppvObject)
return E_POINTER;
if (query_all<Interfaces...>(riid, ppvObject))
{
AddRef();
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override
{
return ++ref_count;
}
ULONG STDMETHODCALLTYPE Release() override
{
ULONG rc = --ref_count;
if (rc == 0)
delete this;
return rc;
}
private:
template <typename Iface, typename... IFaces>
bool query_all(REFIID riid, void** ppvObject)
{
if (riid == __uuidof(Iface)) {
*ppvObject = static_cast<Iface*>(this);
return true;
}
if constexpr (sizeof...(IFaces)) {
return query_all<IFaces...>(riid, ppvObject);
} else if (riid == __uuidof(IUnknown)) {
*ppvObject = static_cast<IUnknown*>(static_cast<Iface*>(this));
return true;
}
return false;
}
std::atomic<ULONG> ref_count { 1 };
};
/*******************************************
* Helper to implement COM/WinRT callbacks *
*******************************************/
template<class Iface, typename F, typename... Args>
struct FFTypedCBHandler : FFComObject<Iface, IAgileObject>
{
using Func = std::decay_t<F>;
explicit FFTypedCBHandler(F&& f) : cb_func(std::forward<F>(f)) {}
std::invoke_result_t<Func&, Args...> STDMETHODCALLTYPE Invoke(Args... args) override
{
if constexpr (std::is_same_v<std::invoke_result_t<Func&, Args...>, HRESULT>) {
return cb_func(std::forward<Args>(args)...);
} else {
cb_func(std::forward<Args>(args)...);
return S_OK;
}
}
private:
Func cb_func;
};
template<class Iface, typename... Args, typename F>
static Microsoft::WRL::ComPtr<Iface> create_cb_handler(F&& cb_func)
{
return Microsoft::WRL::ComPtr<Iface>(
new FFTypedCBHandler<Iface, F, Args...>(std::forward<F>(cb_func))
);
}
/******************************************
* Helpers to implement C style callbacks *
******************************************/
template <typename Ret, typename... Args>
struct Win32Callback {
std::function<Ret(Args...)> fn;
static Ret CALLBACK thunk(Args... args, LPARAM lparam) {
auto self = reinterpret_cast<Win32Callback*>(lparam);
return self->fn(std::forward<Args>(args)...);
}
decltype(&Win32Callback::thunk) proc = &Win32Callback::thunk;
LPARAM lparam = 0;
};
template <typename Ret, typename... Args>
auto make_win32_callback(const std::function<Ret(Args...)> &&fn) {
using T = Win32Callback<Ret, Args...>;
auto res = std::make_unique<T>(T{ std::forward<decltype(fn)>(fn) });
res->lparam = reinterpret_cast<LPARAM>(res.get());
return res;
}
#define make_win32_callback(...) make_win32_callback(std::function(__VA_ARGS__))
/*****************************
* Small convenience helpers *
*****************************/
struct HMODULEDeleter {
typedef HMODULE pointer;
void operator()(HMODULE handle) const {
if (handle)
FreeLibrary(handle);
}
};
typedef std::unique_ptr<HMODULE, HMODULEDeleter> hmodule_ptr_t;
struct HANDLEDeleter {
typedef HANDLE pointer;
void operator()(HANDLE handle) const {
if (handle && handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
}
};
typedef std::unique_ptr<HANDLE, HANDLEDeleter> handle_ptr_t;
#define HLSL(shader) #shader
#endif /* AVFILTER_VSRC_GFXCAPTURE_WINRT_H */