FFmpeg
vsrc_ddagrab.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config.h"
20 
21 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0A00
22 #undef _WIN32_WINNT
23 #define _WIN32_WINNT 0x0A00
24 #endif
25 
26 #include <windows.h>
27 
28 #define COBJMACROS
29 
30 #include <initguid.h>
31 #include <d3d11.h>
32 #include <dxgi1_2.h>
33 #if HAVE_IDXGIOUTPUT5
34 #include <dxgi1_5.h>
35 #endif
36 
37 #include "libavutil/opt.h"
38 #include "libavutil/time.h"
39 #include "libavutil/avstring.h"
40 #include "libavutil/avassert.h"
41 #include "libavutil/hwcontext.h"
43 #include "compat/w32dlfcn.h"
44 #include "avfilter.h"
45 #include "internal.h"
46 #include "video.h"
47 
48 #include "vsrc_ddagrab_shaders.h"
49 
50 // avutil/time.h takes and returns time in microseconds
51 #define TIMER_RES 1000000
52 #define TIMER_RES64 INT64_C(1000000)
53 
54 typedef struct DdagrabContext {
55  const AVClass *class;
56 
60 
64 
65  DXGI_OUTPUT_DESC output_desc;
66  IDXGIOutputDuplication *dxgi_outdupl;
68 
70  ID3D11Texture2D *mouse_texture;
71  ID3D11ShaderResourceView* mouse_resource_view;
72  ID3D11Texture2D *mouse_xor_texture;
73  ID3D11ShaderResourceView* mouse_xor_resource_view;
74 
76  int64_t time_frame;
77  int64_t time_timeout;
78  int64_t first_pts;
79 
80  DXGI_FORMAT raw_format;
81  int raw_width;
83 
84  ID3D11Texture2D *probed_texture;
85  ID3D11Texture2D *buffer_texture;
86 
87  ID3D11VertexShader *vertex_shader;
88  ID3D11InputLayout *input_layout;
89  ID3D11PixelShader *pixel_shader;
90  ID3D11Buffer *const_buffer;
91  ID3D11SamplerState *sampler_state;
92  ID3D11BlendState *blend_state;
93  ID3D11BlendState *blend_state_xor;
94 
98  int width;
99  int height;
100  int offset_x;
101  int offset_y;
102  int out_fmt;
107 
108 #define OFFSET(x) offsetof(DdagrabContext, x)
109 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
110 static const AVOption ddagrab_options[] = {
111  { "output_idx", "dda output index to capture", OFFSET(output_idx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
112  { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
113  { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "30" }, 0, INT_MAX, FLAGS },
114  { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS },
115  { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
116  { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
117  { "output_fmt", "desired output format", OFFSET(out_fmt), AV_OPT_TYPE_INT, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
118  { "auto", "let dda pick its preferred format", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
119  { "8bit", "only output default 8 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
120  { "bgra", "only output 8 Bit BGRA", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_B8G8R8A8_UNORM }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
121  { "10bit", "only output default 10 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R10G10B10A2_UNORM }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
122  { "x2bgr10", "only output 10 Bit X2BGR10", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R10G10B10A2_UNORM }, 0, INT_MAX, FLAGS, .unit = "output_fmt" },
123  { "16bit", "only output default 16 Bit format", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R16G16B16A16_FLOAT },0, INT_MAX, FLAGS, .unit = "output_fmt" },
124  { "rgbaf16", "only output 16 Bit RGBAF16", 0, AV_OPT_TYPE_CONST, { .i64 = DXGI_FORMAT_R16G16B16A16_FLOAT },0, INT_MAX, FLAGS, .unit = "output_fmt" },
125  { "allow_fallback", "don't error on fallback to default 8 Bit format",
126  OFFSET(allow_fallback), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
127  { "force_fmt", "exclude BGRA from format list (experimental, discouraged by Microsoft)",
128  OFFSET(force_fmt), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
129  { "dup_frames", "duplicate frames to maintain framerate",
130  OFFSET(dup_frames), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
131  { NULL }
132 };
133 
134 AVFILTER_DEFINE_CLASS(ddagrab);
135 
136 static inline void release_resource(void *resource)
137 {
138  IUnknown **resp = (IUnknown**)resource;
139  if (*resp) {
140  IUnknown_Release(*resp);
141  *resp = NULL;
142  }
143 }
144 
146 {
147  DdagrabContext *dda = avctx->priv;
148 
156 
159 
165 
166  av_frame_free(&dda->last_frame);
169 }
170 
172 {
173  DdagrabContext *dda = avctx->priv;
174  IDXGIDevice *dxgi_device = NULL;
175  IDXGIAdapter *dxgi_adapter = NULL;
176  IDXGIOutput *dxgi_output = NULL;
177  IDXGIOutput1 *dxgi_output1 = NULL;
178 #if HAVE_IDXGIOUTPUT5 && HAVE_DPI_AWARENESS_CONTEXT
179  IDXGIOutput5 *dxgi_output5 = NULL;
180 
181  typedef DPI_AWARENESS_CONTEXT (*set_thread_dpi_t)(DPI_AWARENESS_CONTEXT);
182  set_thread_dpi_t set_thread_dpi;
183  HMODULE user32_module;
184 #endif
185  int w, h;
186  HRESULT hr;
187 
188  hr = ID3D11Device_QueryInterface(dda->device_hwctx->device, &IID_IDXGIDevice, (void**)&dxgi_device);
189  if (FAILED(hr)) {
190  av_log(avctx, AV_LOG_ERROR, "Failed querying IDXGIDevice\n");
191  return AVERROR_EXTERNAL;
192  }
193 
194  hr = IDXGIDevice_GetParent(dxgi_device, &IID_IDXGIAdapter, (void**)&dxgi_adapter);
195  IDXGIDevice_Release(dxgi_device);
196  dxgi_device = NULL;
197  if (FAILED(hr)) {
198  av_log(avctx, AV_LOG_ERROR, "Failed getting parent IDXGIAdapter\n");
199  return AVERROR_EXTERNAL;
200  }
201 
202  hr = IDXGIAdapter_EnumOutputs(dxgi_adapter, dda->output_idx, &dxgi_output);
203  IDXGIAdapter_Release(dxgi_adapter);
204  dxgi_adapter = NULL;
205  if (FAILED(hr)) {
206  av_log(avctx, AV_LOG_ERROR, "Failed to enumerate DXGI output %d\n", dda->output_idx);
207  return AVERROR_EXTERNAL;
208  }
209 
210  hr = IDXGIOutput_GetDesc(dxgi_output, &dda->output_desc);
211  if (FAILED(hr)) {
212  IDXGIOutput_Release(dxgi_output);
213  av_log(avctx, AV_LOG_ERROR, "Failed getting output description\n");
214  return AVERROR_EXTERNAL;
215  }
216 
217 #if HAVE_IDXGIOUTPUT5 && HAVE_DPI_AWARENESS_CONTEXT
218  user32_module = dlopen("user32.dll", 0);
219  if (!user32_module) {
220  av_log(avctx, AV_LOG_ERROR, "Failed loading user32.dll\n");
221  return AVERROR_EXTERNAL;
222  }
223 
224  set_thread_dpi = (set_thread_dpi_t)dlsym(user32_module, "SetThreadDpiAwarenessContext");
225 
226  if (set_thread_dpi)
227  hr = IDXGIOutput_QueryInterface(dxgi_output, &IID_IDXGIOutput5, (void**)&dxgi_output5);
228 
229  if (set_thread_dpi && SUCCEEDED(hr)) {
230  DPI_AWARENESS_CONTEXT prev_dpi_ctx;
231  DXGI_FORMAT formats[] = {
233  DXGI_FORMAT_R10G10B10A2_UNORM,
235  };
236  int nb_formats = FF_ARRAY_ELEMS(formats);
237 
238  if(dda->out_fmt == DXGI_FORMAT_B8G8R8A8_UNORM) {
240  nb_formats = 1;
241  } else if (dda->out_fmt) {
242  formats[0] = dda->out_fmt;
244  nb_formats = dda->force_fmt ? 1 : 2;
245  }
246 
247  IDXGIOutput_Release(dxgi_output);
248  dxgi_output = NULL;
249 
250  prev_dpi_ctx = set_thread_dpi(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
251  if (!prev_dpi_ctx)
252  av_log(avctx, AV_LOG_WARNING, "Failed enabling DPI awareness for DDA\n");
253 
254  hr = IDXGIOutput5_DuplicateOutput1(dxgi_output5,
255  (IUnknown*)dda->device_hwctx->device,
256  0,
257  nb_formats,
258  formats,
259  &dda->dxgi_outdupl);
260  IDXGIOutput5_Release(dxgi_output5);
261  dxgi_output5 = NULL;
262 
263  if (prev_dpi_ctx)
264  set_thread_dpi(prev_dpi_ctx);
265 
266  dlclose(user32_module);
267  user32_module = NULL;
268  set_thread_dpi = NULL;
269 
270  av_log(avctx, AV_LOG_DEBUG, "Using IDXGIOutput5 interface\n");
271  } else {
272  dlclose(user32_module);
273  user32_module = NULL;
274  set_thread_dpi = NULL;
275 
276  av_log(avctx, AV_LOG_DEBUG, "Falling back to IDXGIOutput1\n");
277 #else
278  {
279 #endif
280  if (dda->out_fmt && dda->out_fmt != DXGI_FORMAT_B8G8R8A8_UNORM && (!dda->allow_fallback || dda->force_fmt)) {
281  av_log(avctx, AV_LOG_ERROR, "Only 8 bit output supported with legacy API\n");
282  return AVERROR(ENOTSUP);
283  }
284 
285  hr = IDXGIOutput_QueryInterface(dxgi_output, &IID_IDXGIOutput1, (void**)&dxgi_output1);
286  IDXGIOutput_Release(dxgi_output);
287  dxgi_output = NULL;
288  if (FAILED(hr)) {
289  av_log(avctx, AV_LOG_ERROR, "Failed querying IDXGIOutput1\n");
290  return AVERROR_EXTERNAL;
291  }
292 
293  hr = IDXGIOutput1_DuplicateOutput(dxgi_output1,
294  (IUnknown*)dda->device_hwctx->device,
295  &dda->dxgi_outdupl);
296  IDXGIOutput1_Release(dxgi_output1);
297  dxgi_output1 = NULL;
298  }
299 
300  if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
301  av_log(avctx, AV_LOG_ERROR, "Too many open duplication sessions\n");
302  return AVERROR(EBUSY);
303  } else if (hr == DXGI_ERROR_UNSUPPORTED) {
304  av_log(avctx, AV_LOG_ERROR, "Selected output not supported\n");
305  return AVERROR_EXTERNAL;
306  } else if (hr == E_INVALIDARG) {
307  av_log(avctx, AV_LOG_ERROR, "Invalid output duplication argument\n");
308  return AVERROR(EINVAL);
309  } else if (hr == E_ACCESSDENIED) {
310  av_log(avctx, AV_LOG_ERROR, "Desktop duplication access denied\n");
311  return AVERROR(EPERM);
312  } else if (FAILED(hr)) {
313  av_log(avctx, AV_LOG_ERROR, "Failed duplicating output\n");
314  return AVERROR_EXTERNAL;
315  }
316 
317  w = dda->output_desc.DesktopCoordinates.right - dda->output_desc.DesktopCoordinates.left;
318  h = dda->output_desc.DesktopCoordinates.bottom - dda->output_desc.DesktopCoordinates.top;
319  av_log(avctx, AV_LOG_VERBOSE, "Opened dxgi output %d with dimensions %dx%d\n", dda->output_idx, w, h);
320 
321  return 0;
322 }
323 
324 typedef struct ConstBufferData
325 {
326  float width;
327  float height;
328 
329  uint64_t padding;
331 
332 static const D3D11_INPUT_ELEMENT_DESC vertex_shader_input_layout[] =
333 {
334  { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
335  { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
336 };
337 
339 {
340  DdagrabContext *dda = avctx->priv;
341  ID3D11Device *dev = dda->device_hwctx->device;
342  D3D11_SAMPLER_DESC sampler_desc = { 0 };
343  D3D11_BLEND_DESC blend_desc = { 0 };
344  D3D11_BUFFER_DESC buffer_desc = { 0 };
345  D3D11_SUBRESOURCE_DATA buffer_data = { 0 };
346  ConstBufferData const_data = { 0 };
347  HRESULT hr;
348 
349  hr = ID3D11Device_CreateVertexShader(dev,
352  NULL,
353  &dda->vertex_shader);
354  if (FAILED(hr)) {
355  av_log(avctx, AV_LOG_ERROR, "CreateVertexShader failed: %lx\n", hr);
356  return AVERROR_EXTERNAL;
357  }
358 
359  hr = ID3D11Device_CreateInputLayout(dev,
364  &dda->input_layout);
365  if (FAILED(hr)) {
366  av_log(avctx, AV_LOG_ERROR, "CreateInputLayout failed: %lx\n", hr);
367  return AVERROR_EXTERNAL;
368  }
369 
370  hr = ID3D11Device_CreatePixelShader(dev,
373  NULL,
374  &dda->pixel_shader);
375  if (FAILED(hr)) {
376  av_log(avctx, AV_LOG_ERROR, "CreatePixelShader failed: %lx\n", hr);
377  return AVERROR_EXTERNAL;
378  }
379 
380  const_data = (ConstBufferData){ dda->width, dda->height };
381 
382  buffer_data.pSysMem = &const_data;
383  buffer_desc.ByteWidth = sizeof(const_data);
384  buffer_desc.Usage = D3D11_USAGE_IMMUTABLE;
385  buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
386  hr = ID3D11Device_CreateBuffer(dev,
387  &buffer_desc,
388  &buffer_data,
389  &dda->const_buffer);
390  if (FAILED(hr)) {
391  av_log(avctx, AV_LOG_ERROR, "CreateBuffer const buffer failed: %lx\n", hr);
392  return AVERROR_EXTERNAL;
393  }
394 
395  sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
396  sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
397  sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
398  sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
399  sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
400  hr = ID3D11Device_CreateSamplerState(dev,
401  &sampler_desc,
402  &dda->sampler_state);
403  if (FAILED(hr)) {
404  av_log(avctx, AV_LOG_ERROR, "CreateSamplerState failed: %lx\n", hr);
405  return AVERROR_EXTERNAL;
406  }
407 
408  blend_desc.AlphaToCoverageEnable = FALSE;
409  blend_desc.IndependentBlendEnable = FALSE;
410  blend_desc.RenderTarget[0].BlendEnable = TRUE;
411  blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
412  blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
413  blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
414  blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
415  blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
416  blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
417  blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
418  hr = ID3D11Device_CreateBlendState(dev,
419  &blend_desc,
420  &dda->blend_state);
421  if (FAILED(hr)) {
422  av_log(avctx, AV_LOG_ERROR, "CreateBlendState failed: %lx\n", hr);
423  return AVERROR_EXTERNAL;
424  }
425 
426  blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_DEST_COLOR;
427  blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
428  hr = ID3D11Device_CreateBlendState(dev,
429  &blend_desc,
430  &dda->blend_state_xor);
431  if (FAILED(hr)) {
432  av_log(avctx, AV_LOG_ERROR, "CreateBlendState (xor) failed: %lx\n", hr);
433  return AVERROR_EXTERNAL;
434  }
435 
436  return 0;
437 }
438 
440 {
441  DdagrabContext *dda = avctx->priv;
442 
443  dda->last_frame = av_frame_alloc();
444  if (!dda->last_frame)
445  return AVERROR(ENOMEM);
446 
447  dda->mouse_x = -1;
448  dda->mouse_y = -1;
449 
450  return 0;
451 }
452 
454  uint8_t *buf,
455  DXGI_OUTDUPL_POINTER_SHAPE_INFO *shape_info,
456  ID3D11Texture2D **out_tex,
457  ID3D11ShaderResourceView **res_view)
458 {
459  DdagrabContext *dda = avctx->priv;
460  D3D11_TEXTURE2D_DESC desc = { 0 };
461  D3D11_SUBRESOURCE_DATA init_data = { 0 };
462  D3D11_SHADER_RESOURCE_VIEW_DESC resource_desc = { 0 };
463  HRESULT hr;
464 
465  desc.MipLevels = 1;
466  desc.ArraySize = 1;
468  desc.SampleDesc.Count = 1;
469  desc.SampleDesc.Quality = 0;
470  desc.Usage = D3D11_USAGE_IMMUTABLE;
471  desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
472 
473  desc.Width = shape_info->Width;
474  desc.Height = shape_info->Height;
475 
476  init_data.pSysMem = buf;
477  init_data.SysMemPitch = shape_info->Pitch;
478 
479  resource_desc.Format = desc.Format;
480  resource_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
481  resource_desc.Texture2D.MostDetailedMip = 0;
482  resource_desc.Texture2D.MipLevels = 1;
483 
484  hr = ID3D11Device_CreateTexture2D(dda->device_hwctx->device,
485  &desc,
486  &init_data,
487  out_tex);
488  if (FAILED(hr)) {
489  av_log(avctx, AV_LOG_ERROR, "Failed creating pointer texture\n");
490  return AVERROR_EXTERNAL;
491  }
492 
493  hr = ID3D11Device_CreateShaderResourceView(dda->device_hwctx->device,
494  (ID3D11Resource*)*out_tex,
495  &resource_desc,
496  res_view);
497  if (FAILED(hr)) {
498  release_resource(out_tex);
499  av_log(avctx, AV_LOG_ERROR, "CreateShaderResourceView for mouse failed: %lx\n", hr);
500  return AVERROR_EXTERNAL;
501  }
502 
503  return 0;
504 }
505 
506 static int convert_mono_buffer(uint8_t *input, uint8_t **rgba_out, uint8_t **xor_out, int *_width, int *_height, int *_pitch)
507 {
508  int width = *_width, height = *_height, pitch = *_pitch;
509  int real_height = height / 2;
510  int size = real_height * pitch;
511 
512  uint8_t *output = av_malloc(real_height * width * 4);
513  uint8_t *output_xor = av_malloc(real_height * width * 4);
514 
515  int y, x;
516 
517  if (!output || !output_xor) {
518  av_free(output);
519  av_free(output_xor);
520  return AVERROR(ENOMEM);
521  }
522 
523  for (y = 0; y < real_height; y++) {
524  for (x = 0; x < width; x++) {
525  int in_pos = (y * pitch) + (x / 8);
526  int out_pos = 4 * ((y * width) + x);
527  int and_val = (input[in_pos] >> (7 - (x % 8))) & 1;
528  int xor_val = (input[in_pos + size] >> (7 - (x % 8))) & 1;
529 
530  if (!and_val && !xor_val) {
531  // solid black
532  memset(&output[out_pos], 0, 4);
533  output[out_pos + 3] = 0xFF;
534 
535  // transparent
536  memset(&output_xor[out_pos], 0, 4);
537  } else if (and_val && !xor_val) {
538  // transparent
539  memset(&output[out_pos], 0, 4);
540 
541  // transparent
542  memset(&output_xor[out_pos], 0, 4);
543  } else if (!and_val && xor_val) {
544  // solid white
545  memset(&output[out_pos], 0xFF, 4);
546 
547  // transparent
548  memset(&output_xor[out_pos], 0, 4);
549  } else if (and_val && xor_val) {
550  // transparent
551  memset(&output[out_pos], 0, 4);
552 
553  // solid white -> invert color
554  memset(&output_xor[out_pos], 0xFF, 4);
555  }
556  }
557  }
558 
559  *_pitch = width * 4;
560  *_height = real_height;
561  *rgba_out = output;
562  *xor_out = output_xor;
563 
564  return 0;
565 }
566 
567 static int fixup_color_mask(uint8_t *input, uint8_t **rgba_out, uint8_t **xor_out, int width, int height, int pitch)
568 {
569  int size = height * pitch;
570  uint8_t *output = av_malloc(size);
571  uint8_t *output_xor = av_malloc(size);
572  int x, y;
573 
574  if (!output || !output_xor) {
575  av_free(output);
576  av_free(output_xor);
577  return AVERROR(ENOMEM);
578  }
579 
580  memcpy(output, input, size);
581  memcpy(output_xor, input, size);
582 
583  for (y = 0; y < height; y++) {
584  for (x = 0; x < width; x++) {
585  int pos = (y*pitch) + (4*x) + 3;
586  output[pos] = input[pos] ? 0 : 0xFF;
587  output_xor[pos] = input[pos] ? 0xFF : 0;
588  }
589  }
590 
591  *rgba_out = output;
592  *xor_out = output_xor;
593 
594  return 0;
595 }
596 
597 static int update_mouse_pointer(AVFilterContext *avctx, DXGI_OUTDUPL_FRAME_INFO *frame_info)
598 {
599  DdagrabContext *dda = avctx->priv;
600  HRESULT hr;
601  int ret, ret2;
602 
603  if (frame_info->LastMouseUpdateTime.QuadPart == 0)
604  return 0;
605 
606  if (frame_info->PointerPosition.Visible) {
607  switch (dda->output_desc.Rotation) {
608  case DXGI_MODE_ROTATION_ROTATE90:
609  dda->mouse_x = frame_info->PointerPosition.Position.y;
610  dda->mouse_y = dda->output_desc.DesktopCoordinates.right - dda->output_desc.DesktopCoordinates.left - frame_info->PointerPosition.Position.x - 1;
611  break;
612  case DXGI_MODE_ROTATION_ROTATE180:
613  dda->mouse_x = dda->output_desc.DesktopCoordinates.right - dda->output_desc.DesktopCoordinates.left - frame_info->PointerPosition.Position.x - 1;
614  dda->mouse_y = dda->output_desc.DesktopCoordinates.bottom - dda->output_desc.DesktopCoordinates.top - frame_info->PointerPosition.Position.y - 1;
615  break;
616  case DXGI_MODE_ROTATION_ROTATE270:
617  dda->mouse_x = dda->output_desc.DesktopCoordinates.bottom - dda->output_desc.DesktopCoordinates.top - frame_info->PointerPosition.Position.y - 1;
618  dda->mouse_y = frame_info->PointerPosition.Position.x;
619  break;
620  default:
621  dda->mouse_x = frame_info->PointerPosition.Position.x;
622  dda->mouse_y = frame_info->PointerPosition.Position.y;
623  }
624  } else {
625  dda->mouse_x = dda->mouse_y = -1;
626  }
627 
628  if (frame_info->PointerShapeBufferSize) {
629  UINT size = frame_info->PointerShapeBufferSize;
630  DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info;
631  uint8_t *rgba_buf = NULL, *rgb_xor_buf = NULL;
632  uint8_t *buf = av_malloc(size);
633  if (!buf)
634  return AVERROR(ENOMEM);
635 
636  hr = IDXGIOutputDuplication_GetFramePointerShape(dda->dxgi_outdupl,
637  size,
638  buf,
639  &size,
640  &shape_info);
641  if (FAILED(hr)) {
642  av_free(buf);
643  av_log(avctx, AV_LOG_ERROR, "Failed getting pointer shape: %lx\n", hr);
644  return AVERROR_EXTERNAL;
645  }
646 
647  if (shape_info.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME) {
648  ret = convert_mono_buffer(buf, &rgba_buf, &rgb_xor_buf, &shape_info.Width, &shape_info.Height, &shape_info.Pitch);
649  av_freep(&buf);
650  if (ret < 0)
651  return ret;
652  } else if (shape_info.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR) {
653  ret = fixup_color_mask(buf, &rgba_buf, &rgb_xor_buf, shape_info.Width, shape_info.Height, shape_info.Pitch);
654  av_freep(&buf);
655  if (ret < 0)
656  return ret;
657  } else if (shape_info.Type == DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR) {
658  rgba_buf = buf;
659  buf = NULL;
660  } else {
661  av_log(avctx, AV_LOG_WARNING, "Unsupported pointer shape type: %d\n", (int)shape_info.Type);
662  av_freep(&buf);
663  return 0;
664  }
665 
670 
671  ret = create_d3d11_pointer_tex(avctx, rgba_buf, &shape_info, &dda->mouse_texture, &dda->mouse_resource_view);
672  ret2 = rgb_xor_buf ? create_d3d11_pointer_tex(avctx, rgb_xor_buf, &shape_info, &dda->mouse_xor_texture, &dda->mouse_xor_resource_view) : 0;
673  av_freep(&rgba_buf);
674  av_freep(&rgb_xor_buf);
675  if (ret < 0)
676  return ret;
677  if (ret2 < 0)
678  return ret2;
679 
680  av_log(avctx, AV_LOG_VERBOSE, "Updated pointer shape texture\n");
681  }
682 
683  return 0;
684 }
685 
686 static int next_frame_internal(AVFilterContext *avctx, ID3D11Texture2D **desktop_texture, int need_frame)
687 {
688  DXGI_OUTDUPL_FRAME_INFO frame_info;
689  DdagrabContext *dda = avctx->priv;
690  IDXGIResource *desktop_resource = NULL;
691  HRESULT hr;
692  int ret;
693 
694  hr = IDXGIOutputDuplication_AcquireNextFrame(
695  dda->dxgi_outdupl,
696  dda->time_timeout,
697  &frame_info,
698  &desktop_resource);
699  if (hr == DXGI_ERROR_WAIT_TIMEOUT) {
700  return AVERROR(EAGAIN);
701  } else if (FAILED(hr)) {
702  av_log(avctx, AV_LOG_ERROR, "AcquireNextFrame failed: %lx\n", hr);
703  return AVERROR_EXTERNAL;
704  }
705 
706  if (dda->draw_mouse) {
707  ret = update_mouse_pointer(avctx, &frame_info);
708  if (ret < 0)
709  goto error;
710  }
711 
712  if (!frame_info.LastPresentTime.QuadPart || !frame_info.AccumulatedFrames) {
713  if (need_frame) {
714  ret = AVERROR(EAGAIN);
715  goto error;
716  }
717 
718  // Unforunately, we can't rely on the desktop_resource's format in this case.
719  // The API might even return it in with a format that was not in the initial
720  // list of supported formats, and it can change/flicker randomly.
721  // To work around this, return an internal copy of the last valid texture we got.
722  release_resource(&desktop_resource);
723 
724  // The initial probing should make this impossible.
725  if (!dda->buffer_texture) {
726  av_log(avctx, AV_LOG_ERROR, "No buffer texture while operating!\n");
727  ret = AVERROR_BUG;
728  goto error;
729  }
730 
731  av_log(avctx, AV_LOG_TRACE, "Returning internal buffer for a frame!\n");
732  ID3D11Texture2D_AddRef(dda->buffer_texture);
733  *desktop_texture = dda->buffer_texture;
734  return 0;
735  }
736 
737  hr = IDXGIResource_QueryInterface(desktop_resource, &IID_ID3D11Texture2D, (void**)desktop_texture);
738  release_resource(&desktop_resource);
739  if (FAILED(hr)) {
740  av_log(avctx, AV_LOG_ERROR, "DXGIResource QueryInterface failed\n");
742  goto error;
743  }
744 
745  if (!dda->buffer_texture) {
746  D3D11_TEXTURE2D_DESC desc;
747  ID3D11Texture2D_GetDesc(*desktop_texture, &desc);
748  desc.Usage = D3D11_USAGE_DEFAULT;
749  desc.BindFlags = 0;
750  desc.CPUAccessFlags = 0;
751  desc.MiscFlags = 0;
752 
753  hr = ID3D11Device_CreateTexture2D(dda->device_hwctx->device, &desc, NULL, &dda->buffer_texture);
754  if (FAILED(hr)) {
755  release_resource(desktop_texture);
756  av_log(avctx, AV_LOG_ERROR, "Failed creating internal buffer texture.\n");
757  ret = AVERROR(ENOMEM);
758  goto error;
759  }
760  }
761 
762  ID3D11DeviceContext_CopyResource(dda->device_hwctx->device_context,
763  (ID3D11Resource*)dda->buffer_texture,
764  (ID3D11Resource*)*desktop_texture);
765 
766  return 0;
767 
768 error:
769  release_resource(&desktop_resource);
770 
771  hr = IDXGIOutputDuplication_ReleaseFrame(dda->dxgi_outdupl);
772  if (FAILED(hr))
773  av_log(avctx, AV_LOG_ERROR, "DDA error ReleaseFrame failed!\n");
774 
775  return ret;
776 }
777 
779 {
780  DdagrabContext *dda = avctx->priv;
781  D3D11_TEXTURE2D_DESC desc;
782  int ret;
783 
784  av_assert1(!dda->probed_texture);
785 
786  do {
787  ret = next_frame_internal(avctx, &dda->probed_texture, 1);
788  } while(ret == AVERROR(EAGAIN));
789  if (ret < 0)
790  return ret;
791 
792  ID3D11Texture2D_GetDesc(dda->probed_texture, &desc);
793 
794  dda->raw_format = desc.Format;
795  dda->raw_width = desc.Width;
796  dda->raw_height = desc.Height;
797 
798  if (dda->width <= 0)
799  dda->width = dda->raw_width;
800  if (dda->height <= 0)
801  dda->height = dda->raw_height;
802 
803  return 0;
804 }
805 
807 {
808  DdagrabContext *dda = avctx->priv;
809  int ret = 0;
810 
812  if (!dda->frames_ref)
813  return AVERROR(ENOMEM);
816 
818  dda->frames_ctx->width = dda->width;
819  dda->frames_ctx->height = dda->height;
820 
821  switch (dda->raw_format) {
823  av_log(avctx, AV_LOG_VERBOSE, "Probed 8 bit RGB frame format\n");
825  break;
826  case DXGI_FORMAT_R10G10B10A2_UNORM:
827  av_log(avctx, AV_LOG_VERBOSE, "Probed 10 bit RGB frame format\n");
829  break;
831  av_log(avctx, AV_LOG_VERBOSE, "Probed 16 bit float RGB frame format\n");
833  break;
834  default:
835  av_log(avctx, AV_LOG_ERROR, "Unexpected texture output format!\n");
836  return AVERROR_BUG;
837  }
838 
839  if (dda->draw_mouse)
840  dda->frames_hwctx->BindFlags |= D3D11_BIND_RENDER_TARGET;
841 
843  if (ret < 0) {
844  av_log(avctx, AV_LOG_ERROR, "Failed to initialise hardware frames context: %d.\n", ret);
845  goto fail;
846  }
847 
848  return 0;
849 fail:
851  return ret;
852 }
853 
854 static int ddagrab_config_props(AVFilterLink *outlink)
855 {
856  AVFilterContext *avctx = outlink->src;
857  DdagrabContext *dda = avctx->priv;
858  int ret;
859 
860  if (avctx->hw_device_ctx) {
862 
864  av_log(avctx, AV_LOG_ERROR, "Non-D3D11VA input hw_device_ctx\n");
865  return AVERROR(EINVAL);
866  }
867 
868  dda->device_ref = av_buffer_ref(avctx->hw_device_ctx);
869  if (!dda->device_ref)
870  return AVERROR(ENOMEM);
871 
872  av_log(avctx, AV_LOG_VERBOSE, "Using provided hw_device_ctx\n");
873  } else {
875  if (ret < 0) {
876  av_log(avctx, AV_LOG_ERROR, "Failed to create D3D11VA device.\n");
877  return ret;
878  }
879 
881 
882  av_log(avctx, AV_LOG_VERBOSE, "Created internal hw_device_ctx\n");
883  }
884 
886 
887  ret = init_dxgi_dda(avctx);
888  if (ret < 0)
889  return ret;
890 
891  ret = probe_output_format(avctx);
892  if (ret < 0)
893  return ret;
894 
895  if (dda->out_fmt && dda->raw_format != dda->out_fmt && (!dda->allow_fallback || dda->force_fmt)) {
896  av_log(avctx, AV_LOG_ERROR, "Requested output format unavailable.\n");
897  return AVERROR(ENOTSUP);
898  }
899 
900  dda->width -= FFMAX(dda->width - dda->raw_width + dda->offset_x, 0);
901  dda->height -= FFMAX(dda->height - dda->raw_height + dda->offset_y, 0);
902 
903  dda->time_base = av_inv_q(dda->framerate);
905  dda->time_timeout = av_rescale_q(1, dda->time_base, (AVRational) { 1, 1000 }) / 2;
906 
907  if (dda->draw_mouse) {
908  ret = init_render_resources(avctx);
909  if (ret < 0)
910  return ret;
911  }
912 
913  ret = init_hwframes_ctx(avctx);
914  if (ret < 0)
915  return ret;
916 
917  outlink->hw_frames_ctx = av_buffer_ref(dda->frames_ref);
918  if (!outlink->hw_frames_ctx)
919  return AVERROR(ENOMEM);
920 
921  outlink->w = dda->width;
922  outlink->h = dda->height;
923  outlink->time_base = (AVRational){1, TIMER_RES};
924  outlink->frame_rate = dda->framerate;
925 
926  return 0;
927 }
928 
930 {
931  DdagrabContext *dda = avctx->priv;
932  ID3D11DeviceContext *devctx = dda->device_hwctx->device_context;
933  ID3D11Texture2D *frame_tex = (ID3D11Texture2D*)frame->data[0];
934  D3D11_RENDER_TARGET_VIEW_DESC target_desc = { 0 };
935  ID3D11RenderTargetView* target_view = NULL;
936  ID3D11Buffer *mouse_vertex_buffer = NULL;
937  D3D11_TEXTURE2D_DESC tex_desc;
938  int num_vertices = 0;
939  int x, y;
940  HRESULT hr;
941  int ret = 0;
942 
943  if (!dda->mouse_texture || dda->mouse_x < 0 || dda->mouse_y < 0)
944  return 0;
945 
946  ID3D11Texture2D_GetDesc(dda->mouse_texture, &tex_desc);
947 
948  x = dda->mouse_x - dda->offset_x;
949  y = dda->mouse_y - dda->offset_y;
950 
951  if (x >= dda->width || y >= dda->height ||
952  -x >= (int)tex_desc.Width || -y >= (int)tex_desc.Height)
953  return 0;
954 
955  target_desc.Format = dda->raw_format;
956  target_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
957  target_desc.Texture2D.MipSlice = 0;
958 
959  hr = ID3D11Device_CreateRenderTargetView(dda->device_hwctx->device,
960  (ID3D11Resource*)frame_tex,
961  &target_desc,
962  &target_view);
963  if (FAILED(hr)) {
964  av_log(avctx, AV_LOG_ERROR, "CreateRenderTargetView failed: %lx\n", hr);
966  goto end;
967  }
968 
969  ID3D11DeviceContext_ClearState(devctx);
970 
971  {
972  D3D11_VIEWPORT viewport = { 0 };
973  viewport.Width = dda->width;
974  viewport.Height = dda->height;
975  viewport.MinDepth = 0.0f;
976  viewport.MaxDepth = 1.0f;
977 
978  ID3D11DeviceContext_RSSetViewports(devctx, 1, &viewport);
979  }
980 
981  {
982  FLOAT vertices[] = {
983  // x, y, z, u, v
984  x , y + tex_desc.Height, 0.0f, 0.0f, 1.0f,
985  x , y , 0.0f, 0.0f, 0.0f,
986  x + tex_desc.Width, y + tex_desc.Height, 0.0f, 1.0f, 1.0f,
987  x + tex_desc.Width, y , 0.0f, 1.0f, 0.0f,
988  };
989  UINT stride = sizeof(FLOAT) * 5;
990  UINT offset = 0;
991 
992  D3D11_SUBRESOURCE_DATA init_data = { 0 };
993  D3D11_BUFFER_DESC buf_desc = { 0 };
994 
995  switch (dda->output_desc.Rotation) {
996  case DXGI_MODE_ROTATION_ROTATE90:
997  vertices[ 0] = x; vertices[ 1] = y;
998  vertices[ 5] = x; vertices[ 6] = y - tex_desc.Width;
999  vertices[10] = x + tex_desc.Height; vertices[11] = y;
1000  vertices[15] = x + tex_desc.Height; vertices[16] = y - tex_desc.Width;
1001  vertices[ 3] = 0.0f; vertices[ 4] = 0.0f;
1002  vertices[ 8] = 1.0f; vertices[ 9] = 0.0f;
1003  vertices[13] = 0.0f; vertices[14] = 1.0f;
1004  vertices[18] = 1.0f; vertices[19] = 1.0f;
1005  break;
1006  case DXGI_MODE_ROTATION_ROTATE180:
1007  vertices[ 0] = x - tex_desc.Width; vertices[ 1] = y;
1008  vertices[ 5] = x - tex_desc.Width; vertices[ 6] = y - tex_desc.Height;
1009  vertices[10] = x; vertices[11] = y;
1010  vertices[15] = x; vertices[16] = y - tex_desc.Height;
1011  vertices[ 3] = 1.0f; vertices[ 4] = 0.0f;
1012  vertices[ 8] = 1.0f; vertices[ 9] = 1.0f;
1013  vertices[13] = 0.0f; vertices[14] = 0.0f;
1014  vertices[18] = 0.0f; vertices[19] = 1.0f;
1015  break;
1016  case DXGI_MODE_ROTATION_ROTATE270:
1017  vertices[ 0] = x - tex_desc.Height; vertices[ 1] = y + tex_desc.Width;
1018  vertices[ 5] = x - tex_desc.Height; vertices[ 6] = y;
1019  vertices[10] = x; vertices[11] = y + tex_desc.Width;
1020  vertices[15] = x; vertices[16] = y;
1021  vertices[ 3] = 1.0f; vertices[ 4] = 1.0f;
1022  vertices[ 8] = 0.0f; vertices[ 9] = 1.0f;
1023  vertices[13] = 1.0f; vertices[14] = 0.0f;
1024  vertices[18] = 0.0f; vertices[19] = 0.0f;
1025  break;
1026  default:
1027  break;
1028  }
1029 
1030  num_vertices = sizeof(vertices) / (sizeof(FLOAT) * 5);
1031 
1032  buf_desc.Usage = D3D11_USAGE_DEFAULT;
1033  buf_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1034  buf_desc.ByteWidth = sizeof(vertices);
1035  init_data.pSysMem = vertices;
1036 
1037  hr = ID3D11Device_CreateBuffer(dda->device_hwctx->device,
1038  &buf_desc,
1039  &init_data,
1040  &mouse_vertex_buffer);
1041  if (FAILED(hr)) {
1042  av_log(avctx, AV_LOG_ERROR, "CreateBuffer failed: %lx\n", hr);
1044  goto end;
1045  }
1046 
1047  ID3D11DeviceContext_IASetVertexBuffers(devctx, 0, 1, &mouse_vertex_buffer, &stride, &offset);
1048  ID3D11DeviceContext_IASetInputLayout(devctx, dda->input_layout);
1049  ID3D11DeviceContext_IASetPrimitiveTopology(devctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
1050  }
1051 
1052  ID3D11DeviceContext_VSSetShader(devctx, dda->vertex_shader, NULL, 0);
1053  ID3D11DeviceContext_VSSetConstantBuffers(devctx, 0, 1, &dda->const_buffer);
1054  ID3D11DeviceContext_PSSetSamplers(devctx, 0, 1, &dda->sampler_state);
1055  ID3D11DeviceContext_PSSetShaderResources(devctx, 0, 1, &dda->mouse_resource_view);
1056  ID3D11DeviceContext_PSSetShader(devctx, dda->pixel_shader, NULL, 0);
1057 
1058  ID3D11DeviceContext_OMSetBlendState(devctx, dda->blend_state, NULL, 0xFFFFFFFF);
1059  ID3D11DeviceContext_OMSetRenderTargets(devctx, 1, &target_view, NULL);
1060 
1061  ID3D11DeviceContext_Draw(devctx, num_vertices, 0);
1062 
1063  if (dda->mouse_xor_resource_view) {
1064  ID3D11DeviceContext_PSSetShaderResources(devctx, 0, 1, &dda->mouse_xor_resource_view);
1065  ID3D11DeviceContext_OMSetBlendState(devctx, dda->blend_state_xor, NULL, 0xFFFFFFFF);
1066 
1067  ID3D11DeviceContext_Draw(devctx, num_vertices, 0);
1068  }
1069 
1070 end:
1071  release_resource(&mouse_vertex_buffer);
1072  release_resource(&target_view);
1073 
1074  return ret;
1075 }
1076 
1078 {
1079  AVFilterContext *avctx = outlink->src;
1080  DdagrabContext *dda = avctx->priv;
1081 
1082  ID3D11Texture2D *cur_texture = NULL;
1083  D3D11_TEXTURE2D_DESC desc = { 0 };
1084  D3D11_BOX box = { 0 };
1085 
1086  int64_t time_frame = dda->time_frame;
1087  int64_t now, delay;
1088  AVFrame *frame = NULL;
1089  HRESULT hr;
1090  int ret;
1091 
1092  /* time_frame is in units of microseconds divided by the time_base.
1093  * This means that adding a clean 1M to it is the equivalent of adding
1094  * 1M*time_base microseconds to it, except it avoids all rounding error.
1095  * The only time rounding error occurs is when multiplying to calculate
1096  * the delay. So any rounding error there corrects itself over time.
1097  */
1098  time_frame += TIMER_RES64;
1099  for (;;) {
1100  now = av_gettime_relative();
1101  delay = time_frame * av_q2d(dda->time_base) - now;
1102  if (delay <= 0) {
1103  if (delay < -TIMER_RES64 * av_q2d(dda->time_base)) {
1104  time_frame += TIMER_RES64;
1105  }
1106  break;
1107  }
1108  av_usleep(delay);
1109  }
1110 
1111  if (!dda->first_pts)
1112  dda->first_pts = now;
1113  now -= dda->first_pts;
1114 
1115  if (!dda->probed_texture) {
1116  do {
1117  ret = next_frame_internal(avctx, &cur_texture, 0);
1118  } while (ret == AVERROR(EAGAIN) && !dda->dup_frames);
1119  } else {
1120  cur_texture = dda->probed_texture;
1121  dda->probed_texture = NULL;
1122  ret = 0;
1123  }
1124 
1125  if (ret == AVERROR(EAGAIN) && dda->last_frame->buf[0]) {
1126  frame = av_frame_alloc();
1127  if (!frame)
1128  return AVERROR(ENOMEM);
1129 
1130  ret = av_frame_ref(frame, dda->last_frame);
1131  if (ret < 0) {
1132  av_frame_free(&frame);
1133  return ret;
1134  }
1135 
1136  av_log(avctx, AV_LOG_DEBUG, "Duplicated output frame\n");
1137 
1138  goto frame_done;
1139  } else if (ret == AVERROR(EAGAIN)) {
1140  av_log(avctx, AV_LOG_VERBOSE, "Initial DDA AcquireNextFrame timeout!\n");
1141  return AVERROR(EAGAIN);
1142  } else if (ret < 0) {
1143  return ret;
1144  }
1145 
1146  // AcquireNextFrame sometimes has bursts of delay.
1147  // This increases accuracy of the timestamp, but might upset consumers due to more jittery framerate?
1148  now = av_gettime_relative() - dda->first_pts;
1149 
1150  ID3D11Texture2D_GetDesc(cur_texture, &desc);
1151  if (desc.Format != dda->raw_format ||
1152  (int)desc.Width != dda->raw_width ||
1153  (int)desc.Height != dda->raw_height) {
1154  av_log(avctx, AV_LOG_ERROR, "Output parameters changed!\n");
1156  goto fail;
1157  }
1158 
1159  frame = ff_get_video_buffer(outlink, dda->width, dda->height);
1160  if (!frame) {
1161  ret = AVERROR(ENOMEM);
1162  goto fail;
1163  }
1164 
1165  box.left = dda->offset_x;
1166  box.top = dda->offset_y;
1167  box.right = box.left + dda->width;
1168  box.bottom = box.top + dda->height;
1169  box.front = 0;
1170  box.back = 1;
1171 
1172  ID3D11DeviceContext_CopySubresourceRegion(
1174  (ID3D11Resource*)frame->data[0], (UINT)(intptr_t)frame->data[1],
1175  0, 0, 0,
1176  (ID3D11Resource*)cur_texture, 0,
1177  &box);
1178 
1179  release_resource(&cur_texture);
1180 
1181  hr = IDXGIOutputDuplication_ReleaseFrame(dda->dxgi_outdupl);
1182  if (FAILED(hr)) {
1183  av_log(avctx, AV_LOG_ERROR, "DDA ReleaseFrame failed!\n");
1185  goto fail;
1186  }
1187 
1188  if (dda->draw_mouse) {
1189  ret = draw_mouse_pointer(avctx, frame);
1190  if (ret < 0)
1191  goto fail;
1192  }
1193 
1195 
1196  if (desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM ||
1197  desc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) {
1198  // According to MSDN, all integer formats contain sRGB image data
1203  } else if(desc.Format == DXGI_FORMAT_R16G16B16A16_FLOAT) {
1204  // According to MSDN, all floating point formats contain sRGB image data with linear 1.0 gamma.
1209  } else {
1210  ret = AVERROR_BUG;
1211  goto fail;
1212  }
1213 
1215  if (ret < 0)
1216  return ret;
1217 
1218 frame_done:
1219  frame->pts = now;
1220  dda->time_frame = time_frame;
1221 
1222  return ff_filter_frame(outlink, frame);
1223 
1224 fail:
1225  if (frame)
1226  av_frame_free(&frame);
1227 
1228  if (cur_texture)
1229  IDXGIOutputDuplication_ReleaseFrame(dda->dxgi_outdupl);
1230 
1231  release_resource(&cur_texture);
1232  return ret;
1233 }
1234 
1235 static const AVFilterPad ddagrab_outputs[] = {
1236  {
1237  .name = "default",
1238  .type = AVMEDIA_TYPE_VIDEO,
1239  .request_frame = ddagrab_request_frame,
1240  .config_props = ddagrab_config_props,
1241  },
1242 };
1243 
1245  .name = "ddagrab",
1246  .description = NULL_IF_CONFIG_SMALL("Grab Windows Desktop images using Desktop Duplication API"),
1247  .priv_size = sizeof(DdagrabContext),
1248  .priv_class = &ddagrab_class,
1249  .init = ddagrab_init,
1251  .inputs = NULL,
1254  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
1255  .flags = AVFILTER_FLAG_HWDEVICE,
1256 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:31
formats
formats
Definition: signature.h:48
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:112
AVFrame::color_trc
enum AVColorTransferCharacteristic color_trc
Definition: frame.h:658
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
DdagrabContext::raw_height
int raw_height
Definition: vsrc_ddagrab.c:82
av_gettime_relative
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVFrame::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: frame.h:654
TIMER_RES
#define TIMER_RES
Definition: vsrc_ddagrab.c:51
DdagrabContext::force_fmt
int force_fmt
Definition: vsrc_ddagrab.c:104
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
draw_mouse_pointer
static int draw_mouse_pointer(AVFilterContext *avctx, AVFrame *frame)
Definition: vsrc_ddagrab.c:929
FF_FILTER_FLAG_HWFRAME_AWARE
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition: internal.h:351
init_render_resources
static av_cold int init_render_resources(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:338
ConstBufferData::width
float width
Definition: vsrc_ddagrab.c:326
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
DXGI_FORMAT_B8G8R8A8_UNORM
@ DXGI_FORMAT_B8G8R8A8_UNORM
Definition: dds.c:91
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
fixup_color_mask
static int fixup_color_mask(uint8_t *input, uint8_t **rgba_out, uint8_t **xor_out, int width, int height, int pitch)
Definition: vsrc_ddagrab.c:567
AVCOL_TRC_LINEAR
@ AVCOL_TRC_LINEAR
"Linear transfer characteristics"
Definition: pixfmt.h:589
AV_OPT_TYPE_VIDEO_RATE
@ AV_OPT_TYPE_VIDEO_RATE
offset must point to AVRational
Definition: opt.h:248
DdagrabContext::frames_ctx
AVHWFramesContext * frames_ctx
Definition: vsrc_ddagrab.c:62
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:197
next_frame_internal
static int next_frame_internal(AVFilterContext *avctx, ID3D11Texture2D **desktop_texture, int need_frame)
Definition: vsrc_ddagrab.c:686
DdagrabContext::blend_state
ID3D11BlendState * blend_state
Definition: vsrc_ddagrab.c:92
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
AVFrame::color_primaries
enum AVColorPrimaries color_primaries
Definition: frame.h:656
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
DdagrabContext::device_ctx
AVHWDeviceContext * device_ctx
Definition: vsrc_ddagrab.c:58
AVFrame::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:665
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:322
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:375
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:487
w
uint8_t w
Definition: llviddspenc.c:38
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:683
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
AVOption
AVOption.
Definition: opt.h:346
DdagrabContext::frames_hwctx
AVD3D11VAFramesContext * frames_hwctx
Definition: vsrc_ddagrab.c:63
ddagrab_request_frame
static int ddagrab_request_frame(AVFilterLink *outlink)
Definition: vsrc_ddagrab.c:1077
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:610
AVFilterContext::hw_device_ctx
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition: avfilter.h:469
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
DdagrabContext::width
int width
Definition: vsrc_ddagrab.c:98
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
DdagrabContext::first_pts
int64_t first_pts
Definition: vsrc_ddagrab.c:78
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
ff_vsrc_ddagrab
const AVFilter ff_vsrc_ddagrab
Definition: vsrc_ddagrab.c:1244
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:217
video.h
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:588
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:396
DdagrabContext::last_frame
AVFrame * last_frame
Definition: vsrc_ddagrab.c:67
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(ddagrab)
AVD3D11VAFramesContext::BindFlags
UINT BindFlags
D3D11_TEXTURE2D_DESC.BindFlags used for texture creation.
Definition: hwcontext_d3d11va.h:160
vsrc_ddagrab_shaders.h
AVCOL_TRC_IEC61966_2_1
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
Definition: pixfmt.h:594
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:422
fail
#define fail()
Definition: checkasm.h:179
DdagrabContext::pixel_shader
ID3D11PixelShader * pixel_shader
Definition: vsrc_ddagrab.c:89
AV_HWDEVICE_TYPE_D3D11VA
@ AV_HWDEVICE_TYPE_D3D11VA
Definition: hwcontext.h:35
DdagrabContext::framerate
AVRational framerate
Definition: vsrc_ddagrab.c:97
DdagrabContext::mouse_xor_resource_view
ID3D11ShaderResourceView * mouse_xor_resource_view
Definition: vsrc_ddagrab.c:73
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:33
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:148
avassert.h
DdagrabContext::device_hwctx
AVD3D11VADeviceContext * device_hwctx
Definition: vsrc_ddagrab.c:59
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ddagrab_options
static const AVOption ddagrab_options[]
Definition: vsrc_ddagrab.c:110
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
AVHWFramesContext::height
int height
Definition: hwcontext.h:217
width
#define width
AVD3D11VADeviceContext::device
ID3D11Device * device
Device used for texture creation and access.
Definition: hwcontext_d3d11va.h:56
DdagrabContext::raw_width
int raw_width
Definition: vsrc_ddagrab.c:81
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
create_d3d11_pointer_tex
static int create_d3d11_pointer_tex(AVFilterContext *avctx, uint8_t *buf, DXGI_OUTDUPL_POINTER_SHAPE_INFO *shape_info, ID3D11Texture2D **out_tex, ID3D11ShaderResourceView **res_view)
Definition: vsrc_ddagrab.c:453
DdagrabContext::dxgi_outdupl
IDXGIOutputDuplication * dxgi_outdupl
Definition: vsrc_ddagrab.c:66
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
vertex_shader_input_layout
static const D3D11_INPUT_ELEMENT_DESC vertex_shader_input_layout[]
Definition: vsrc_ddagrab.c:332
ConstBufferData
Definition: vsrc_ddagrab.c:324
DdagrabContext::mouse_x
int mouse_x
Definition: vsrc_ddagrab.c:69
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
frame
static AVFrame * frame
Definition: demux_decode.c:54
if
if(ret)
Definition: filter_design.txt:179
ConstBufferData::height
float height
Definition: vsrc_ddagrab.c:327
DdagrabContext::vertex_shader
ID3D11VertexShader * vertex_shader
Definition: vsrc_ddagrab.c:87
framerate
float framerate
Definition: av1_levels.c:29
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
ddagrab_config_props
static int ddagrab_config_props(AVFilterLink *outlink)
Definition: vsrc_ddagrab.c:854
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:210
DdagrabContext::mouse_texture
ID3D11Texture2D * mouse_texture
Definition: vsrc_ddagrab.c:70
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
DdagrabContext::const_buffer
ID3D11Buffer * const_buffer
Definition: vsrc_ddagrab.c:90
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:245
AVCOL_PRI_BT709
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition: pixfmt.h:557
time.h
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
AVD3D11VAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_d3d11va.h:131
ddagrab_uninit
static av_cold void ddagrab_uninit(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:145
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:537
DdagrabContext::mouse_y
int mouse_y
Definition: vsrc_ddagrab.c:69
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:106
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:384
release_resource
static void release_resource(void *resource)
Definition: vsrc_ddagrab.c:136
AVFILTER_FLAG_HWDEVICE
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
Definition: avfilter.h:138
DdagrabContext::out_fmt
int out_fmt
Definition: vsrc_ddagrab.c:102
size
int size
Definition: twinvq_data.h:10344
AVERROR_OUTPUT_CHANGED
#define AVERROR_OUTPUT_CHANGED
Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
Definition: error.h:76
TIMER_RES64
#define TIMER_RES64
Definition: vsrc_ddagrab.c:52
height
#define height
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:336
DdagrabContext::time_base
AVRational time_base
Definition: vsrc_ddagrab.c:75
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
FLAGS
#define FLAGS
Definition: vsrc_ddagrab.c:109
internal.h
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: internal.h:172
DdagrabContext::raw_format
DXGI_FORMAT raw_format
Definition: vsrc_ddagrab.c:80
buffer_data
Definition: avio_read_callback.c:36
DXGI_FORMAT_R16G16B16A16_FLOAT
@ DXGI_FORMAT_R16G16B16A16_FLOAT
Definition: dds.c:62
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
DdagrabContext::mouse_resource_view
ID3D11ShaderResourceView * mouse_resource_view
Definition: vsrc_ddagrab.c:71
AVD3D11VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d11va.h:45
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
DdagrabContext::draw_mouse
int draw_mouse
Definition: vsrc_ddagrab.c:96
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
DdagrabContext::allow_fallback
int allow_fallback
Definition: vsrc_ddagrab.c:103
FLOAT
float FLOAT
Definition: faandct.c:33
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:39
DdagrabContext::offset_y
int offset_y
Definition: vsrc_ddagrab.c:101
stride
#define stride
Definition: h264pred_template.c:537
DdagrabContext::time_timeout
int64_t time_timeout
Definition: vsrc_ddagrab.c:77
AVFilter
Filter definition.
Definition: avfilter.h:166
convert_mono_buffer
static int convert_mono_buffer(uint8_t *input, uint8_t **rgba_out, uint8_t **xor_out, int *_width, int *_height, int *_pitch)
Definition: vsrc_ddagrab.c:506
DdagrabContext::output_idx
int output_idx
Definition: vsrc_ddagrab.c:95
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
ret
ret
Definition: filter_design.txt:187
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:72
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
init_dxgi_dda
static av_cold int init_dxgi_dda(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:171
av_hwdevice_ctx_create
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition: hwcontext.c:600
pos
unsigned int pos
Definition: spdifenc.c:413
DdagrabContext::input_layout
ID3D11InputLayout * input_layout
Definition: vsrc_ddagrab.c:88
AVFrame::sample_aspect_ratio
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition: frame.h:482
DdagrabContext::dup_frames
int dup_frames
Definition: vsrc_ddagrab.c:105
av_frame_replace
int av_frame_replace(AVFrame *dst, const AVFrame *src)
Ensure the destination frame refers to the same data described by the source frame,...
Definition: frame.c:483
DdagrabContext::frames_ref
AVBufferRef * frames_ref
Definition: vsrc_ddagrab.c:61
DdagrabContext::time_frame
int64_t time_frame
Definition: vsrc_ddagrab.c:76
DdagrabContext::height
int height
Definition: vsrc_ddagrab.c:99
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
avfilter.h
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
desc
const char * desc
Definition: libsvtav1.c:75
pixel_shader_bytes
static const uint8_t pixel_shader_bytes[]
Definition: vsrc_ddagrab_shaders.h:101
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
vertex_shader_bytes
static const uint8_t vertex_shader_bytes[]
Definition: vsrc_ddagrab_shaders.h:63
init_hwframes_ctx
static av_cold int init_hwframes_ctx(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:806
DdagrabContext::buffer_texture
ID3D11Texture2D * buffer_texture
Definition: vsrc_ddagrab.c:85
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
update_mouse_pointer
static int update_mouse_pointer(AVFilterContext *avctx, DXGI_OUTDUPL_FRAME_INFO *frame_info)
Definition: vsrc_ddagrab.c:597
AV_PIX_FMT_RGBAF16
#define AV_PIX_FMT_RGBAF16
Definition: pixfmt.h:546
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:251
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:183
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
DdagrabContext::sampler_state
ID3D11SamplerState * sampler_state
Definition: vsrc_ddagrab.c:91
ddagrab_outputs
static const AVFilterPad ddagrab_outputs[]
Definition: vsrc_ddagrab.c:1235
DdagrabContext::offset_x
int offset_x
Definition: vsrc_ddagrab.c:100
DdagrabContext::probed_texture
ID3D11Texture2D * probed_texture
Definition: vsrc_ddagrab.c:84
ddagrab_init
static av_cold int ddagrab_init(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:439
DdagrabContext::output_desc
DXGI_OUTPUT_DESC output_desc
Definition: vsrc_ddagrab.c:65
hwcontext.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
DdagrabContext::device_ref
AVBufferRef * device_ref
Definition: vsrc_ddagrab.c:57
ConstBufferData::padding
uint64_t padding
Definition: vsrc_ddagrab.c:329
AVD3D11VADeviceContext::device_context
ID3D11DeviceContext * device_context
If unset, this will be set from the device field on init.
Definition: hwcontext_d3d11va.h:64
ID3D11Device
void ID3D11Device
Definition: nvenc.h:28
h
h
Definition: vp9dsp_template.c:2038
DdagrabContext
Definition: vsrc_ddagrab.c:54
avstring.h
DdagrabContext::mouse_xor_texture
ID3D11Texture2D * mouse_xor_texture
Definition: vsrc_ddagrab.c:72
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:244
hwcontext_d3d11va.h
OFFSET
#define OFFSET(x)
Definition: vsrc_ddagrab.c:108
probe_output_format
static int probe_output_format(AVFilterContext *avctx)
Definition: vsrc_ddagrab.c:778
w32dlfcn.h
DdagrabContext::blend_state_xor
ID3D11BlendState * blend_state_xor
Definition: vsrc_ddagrab.c:93