FFmpeg
d3d12va_decode.c
Go to the documentation of this file.
1 /*
2  * Direct3D 12 HW acceleration video decoder
3  *
4  * copyright (c) 2022-2023 Wu Jianhua <toqsxw@outlook.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <string.h>
24 #include <initguid.h>
25 
26 #include "libavutil/common.h"
27 #include "libavutil/log.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/time.h"
30 #include "libavutil/imgutils.h"
33 #include "avcodec.h"
34 #include "decode.h"
35 #include "d3d12va_decode.h"
36 #include "dxva2_internal.h"
37 
38 typedef struct HelperObjects {
39  ID3D12CommandAllocator *command_allocator;
40  ID3D12Resource *buffer;
41  uint64_t fence_value;
43 
45 {
46  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
47  return av_image_get_buffer_size(frames_ctx->sw_format, avctx->coded_width, avctx->coded_height, 1);
48 }
49 
52  int curr)
53 {
55  ID3D12Resource *res;
56  unsigned i;
57 
58  f = (AVD3D12VAFrame *)frame->data[0];
59  if (!f)
60  goto fail;
61 
62  res = f->texture;
63  if (!res)
64  goto fail;
65 
66  for (i = 0; i < ctx->max_num_ref; i++) {
67  if (ctx->ref_resources[i] && res == ctx->ref_resources[i]) {
68  ctx->used_mask |= 1 << i;
69  return i;
70  }
71  }
72 
73  if (curr) {
74  for (i = 0; i < ctx->max_num_ref; i++) {
75  if (!((ctx->used_mask >> i) & 0x1)) {
76  ctx->ref_resources[i] = res;
77  return i;
78  }
79  }
80  }
81 
82 fail:
83  av_log((AVCodecContext *)avctx, AV_LOG_WARNING, "Could not get surface index. Using 0 instead.\n");
84  return 0;
85 }
86 
87 static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator,
88  ID3D12Resource **ppBuffer)
89 {
90  HRESULT hr;
92  HelperObjects obj = { 0 };
93  D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
94 
95  D3D12_RESOURCE_DESC desc = {
96  .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
97  .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
98  .Width = ctx->bitstream_size,
99  .Height = 1,
100  .DepthOrArraySize = 1,
101  .MipLevels = 1,
102  .Format = DXGI_FORMAT_UNKNOWN,
103  .SampleDesc = { .Count = 1, .Quality = 0 },
104  .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
105  .Flags = D3D12_RESOURCE_FLAG_NONE,
106  };
107 
108  if (av_fifo_peek(ctx->objects_queue, &obj, 1, 0) >= 0) {
109  uint64_t completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
110  if (completion >= obj.fence_value) {
111  *ppAllocator = obj.command_allocator;
112  *ppBuffer = obj.buffer;
113  av_fifo_read(ctx->objects_queue, &obj, 1);
114  return 0;
115  }
116  }
117 
118  hr = ID3D12Device_CreateCommandAllocator(ctx->device_ctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
119  &IID_ID3D12CommandAllocator, (void **)ppAllocator);
120  if (FAILED(hr)) {
121  av_log(avctx, AV_LOG_ERROR, "Failed to create a new command allocator!\n");
122  return AVERROR(EINVAL);
123  }
124 
125  hr = ID3D12Device_CreateCommittedResource(ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
126  &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
127  &IID_ID3D12Resource, (void **)ppBuffer);
128 
129  if (FAILED(hr)) {
130  av_log(avctx, AV_LOG_ERROR, "Failed to create a new d3d12 buffer!\n");
131  return AVERROR(EINVAL);
132  }
133 
134  return 0;
135 }
136 
137 static int d3d12va_discard_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator,
138  ID3D12Resource *pBuffer, uint64_t fence_value)
139 {
141 
142  HelperObjects obj = {
143  .command_allocator = pAllocator,
144  .buffer = pBuffer,
145  .fence_value = fence_value,
146  };
147 
148  if (av_fifo_write(ctx->objects_queue, &obj, 1) < 0) {
149  D3D12_OBJECT_RELEASE(pAllocator);
150  D3D12_OBJECT_RELEASE(pBuffer);
151  return AVERROR(ENOMEM);
152  }
153 
154  return 0;
155 }
156 
158 {
159  uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->fence);
160  if (completion < psync_ctx->fence_value) {
161  if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->fence, psync_ctx->fence_value, psync_ctx->event)))
162  return AVERROR(EINVAL);
163 
164  WaitForSingleObjectEx(psync_ctx->event, INFINITE, FALSE);
165  }
166 
167  return 0;
168 }
169 
170 static void bufref_free_interface(void *opaque, uint8_t *data)
171 {
172  D3D12_OBJECT_RELEASE(opaque);
173 }
174 
175 static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
176 {
177  return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
178 }
179 
181 {
183 
184  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
185  return d3d12va_fence_completion(&ctx->sync_ctx);
186 
187 fail:
188  return AVERROR(EINVAL);
189 }
190 
192 {
194  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
195  AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx;
196  AVD3D12VAFramesContext *frames_hwctx = frames_ctx->hwctx;
197 
198  D3D12_VIDEO_DECODER_HEAP_DESC desc = {
199  .NodeMask = 0,
200  .Configuration = ctx->cfg,
201  .DecodeWidth = frames_ctx->width,
202  .DecodeHeight = frames_ctx->height,
203  .Format = frames_hwctx->format,
204  .FrameRate = { avctx->framerate.num, avctx->framerate.den },
205  .BitRate = avctx->bit_rate,
206  .MaxDecodePictureBufferCount = ctx->max_num_ref,
207  };
208 
209  DX_CHECK(ID3D12VideoDevice_CreateVideoDecoderHeap(device_hwctx->video_device, &desc,
210  &IID_ID3D12VideoDecoderHeap, (void **)&ctx->decoder_heap));
211 
212  return 0;
213 
214 fail:
215  if (ctx->decoder) {
216  av_log(avctx, AV_LOG_ERROR, "D3D12 doesn't support decoding frames with an extent "
217  "[width(%d), height(%d)], on your device!\n", frames_ctx->width, frames_ctx->height);
218  }
219 
220  return AVERROR(EINVAL);
221 }
222 
224 {
225  D3D12_VIDEO_DECODER_DESC desc;
227  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
228  AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx;
229  AVD3D12VAFramesContext *frames_hwctx = frames_ctx->hwctx;
230 
231  D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT feature = {
232  .NodeIndex = 0,
233  .Configuration = ctx->cfg,
234  .Width = frames_ctx->width,
235  .Height = frames_ctx->height,
236  .DecodeFormat = frames_hwctx->format,
237  .FrameRate = { avctx->framerate.num, avctx->framerate.den },
238  .BitRate = avctx->bit_rate,
239  };
240 
241  DX_CHECK(ID3D12VideoDevice_CheckFeatureSupport(device_hwctx->video_device, D3D12_FEATURE_VIDEO_DECODE_SUPPORT,
242  &feature, sizeof(feature)));
243  if (!(feature.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED)) {
244  av_log(avctx, AV_LOG_ERROR, "D3D12 video decode is not supported on this device.\n");
245  return AVERROR(ENOSYS);
246  }
247  if (!(feature.DecodeTier >= D3D12_VIDEO_DECODE_TIER_2)) {
248  av_log(avctx, AV_LOG_ERROR, "D3D12 video decode on this device requires tier %d support, "
249  "but it is not implemented.\n", feature.DecodeTier);
250  return AVERROR_PATCHWELCOME;
251  }
252 
253  desc = (D3D12_VIDEO_DECODER_DESC) {
254  .NodeMask = 0,
255  .Configuration = ctx->cfg,
256  };
257 
258  DX_CHECK(ID3D12VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc, &IID_ID3D12VideoDecoder,
259  (void **)&ctx->decoder));
260 
261  ctx->decoder_ref = bufref_wrap_interface((IUnknown *)ctx->decoder);
262  if (!ctx->decoder_ref)
263  return AVERROR(ENOMEM);
264 
265  return 0;
266 
267 fail:
268  return AVERROR(EINVAL);
269 }
270 
272 {
273  AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data;
274 
275  frames_ctx->format = AV_PIX_FMT_D3D12;
277  frames_ctx->width = avctx->width;
278  frames_ctx->height = avctx->height;
279 
280  return 0;
281 }
282 
284 {
285  int ret;
286  AVHWFramesContext *frames_ctx;
288  ID3D12Resource *buffer = NULL;
289  ID3D12CommandAllocator *command_allocator = NULL;
290  D3D12_COMMAND_QUEUE_DESC queue_desc = {
291  .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
292  .Priority = 0,
293  .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
294  .NodeMask = 0,
295  };
296 
297  ctx->pix_fmt = avctx->hwaccel->pix_fmt;
298 
300  if (ret < 0)
301  return ret;
302 
303  frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
304  ctx->device_ctx = (AVD3D12VADeviceContext *)frames_ctx->device_ctx->hwctx;
305 
306  if (frames_ctx->format != ctx->pix_fmt) {
307  av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n");
308  goto fail;
309  }
310 
311  ret = d3d12va_create_decoder(avctx);
312  if (ret < 0)
313  goto fail;
314 
316  if (ret < 0)
317  goto fail;
318 
319  ctx->bitstream_size = ff_d3d12va_get_suitable_max_bitstream_size(avctx);
320 
321  ctx->ref_resources = av_calloc(ctx->max_num_ref, sizeof(*ctx->ref_resources));
322  if (!ctx->ref_resources)
323  return AVERROR(ENOMEM);
324 
325  ctx->ref_subresources = av_calloc(ctx->max_num_ref, sizeof(*ctx->ref_subresources));
326  if (!ctx->ref_subresources)
327  return AVERROR(ENOMEM);
328 
331  if (!ctx->objects_queue)
332  return AVERROR(ENOMEM);
333 
334  DX_CHECK(ID3D12Device_CreateFence(ctx->device_ctx->device, 0, D3D12_FENCE_FLAG_NONE,
335  &IID_ID3D12Fence, (void **)&ctx->sync_ctx.fence));
336 
337  ctx->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
338  if (!ctx->sync_ctx.event)
339  goto fail;
340 
341  ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
342  if (ret < 0)
343  goto fail;
344 
345  DX_CHECK(ID3D12Device_CreateCommandQueue(ctx->device_ctx->device, &queue_desc,
346  &IID_ID3D12CommandQueue, (void **)&ctx->command_queue));
347 
348  DX_CHECK(ID3D12Device_CreateCommandList(ctx->device_ctx->device, 0, queue_desc.Type,
349  command_allocator, NULL, &IID_ID3D12CommandList, (void **)&ctx->command_list));
350 
351  DX_CHECK(ID3D12VideoDecodeCommandList_Close(ctx->command_list));
352 
353  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
354 
355  ret = d3d12va_sync_with_gpu(avctx);
356  if (ret < 0)
357  goto fail;
358 
359  d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
360  if (ret < 0)
361  goto fail;
362 
363  return 0;
364 
365 fail:
366  D3D12_OBJECT_RELEASE(command_allocator);
369 
370  return AVERROR(EINVAL);
371 }
372 
374 {
375  int num_allocator = 0;
377  HelperObjects obj;
378 
379  if (ctx->sync_ctx.fence)
380  d3d12va_sync_with_gpu(avctx);
381 
382  av_freep(&ctx->ref_resources);
383  av_freep(&ctx->ref_subresources);
384 
385  D3D12_OBJECT_RELEASE(ctx->command_list);
386  D3D12_OBJECT_RELEASE(ctx->command_queue);
387 
388  if (ctx->objects_queue) {
389  while (av_fifo_read(ctx->objects_queue, &obj, 1) >= 0) {
390  num_allocator++;
393  }
394 
395  av_log(avctx, AV_LOG_VERBOSE, "Total number of command allocators reused: %d\n", num_allocator);
396  }
397 
398  av_fifo_freep2(&ctx->objects_queue);
399 
400  D3D12_OBJECT_RELEASE(ctx->sync_ctx.fence);
401  if (ctx->sync_ctx.event)
402  CloseHandle(ctx->sync_ctx.event);
403 
404  D3D12_OBJECT_RELEASE(ctx->decoder_heap);
405 
406  av_buffer_unref(&ctx->decoder_ref);
407 
408  return 0;
409 }
410 
411 static inline int d3d12va_update_reference_frames_state(AVCodecContext *avctx, D3D12_RESOURCE_BARRIER *barriers,
412  ID3D12Resource *current_resource, int state_before, int state_end)
413 {
415 
416  int num_barrier = 0;
417  for (int i = 0; i < ctx->max_num_ref; i++) {
418  if (((ctx->used_mask >> i) & 0x1) && ctx->ref_resources[i] && ctx->ref_resources[i] != current_resource) {
419  barriers[num_barrier].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
420  barriers[num_barrier].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
421  barriers[num_barrier].Transition = (D3D12_RESOURCE_TRANSITION_BARRIER){
422  .pResource = ctx->ref_resources[i],
423  .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
424  .StateBefore = state_before,
425  .StateAfter = state_end,
426  };
427  num_barrier++;
428  }
429  }
430 
431  return num_barrier;
432 }
433 
435  const void *pp, unsigned pp_size,
436  const void *qm, unsigned qm_size,
437  int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
438 {
439  int ret;
441  ID3D12Resource *buffer = NULL;
442  ID3D12CommandAllocator *command_allocator = NULL;
443  AVD3D12VAFrame *f = (AVD3D12VAFrame *)frame->data[0];
444  ID3D12Resource *resource = (ID3D12Resource *)f->texture;
445 
446  ID3D12VideoDecodeCommandList *cmd_list = ctx->command_list;
447  D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
448 
449  D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS input_args = {
450  .NumFrameArguments = 2,
451  .FrameArguments = {
452  [0] = {
453  .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_PICTURE_PARAMETERS,
454  .Size = pp_size,
455  .pData = (void *)pp,
456  },
457  [1] = {
458  .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
459  .Size = qm_size,
460  .pData = (void *)qm,
461  },
462  },
463  .pHeap = ctx->decoder_heap,
464  };
465 
466  D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS output_args = {
467  .ConversionArguments = { 0 },
468  .OutputSubresource = 0,
469  .pOutputTexture2D = resource,
470  };
471 
472  UINT num_barrier = 1;
473  barriers[0] = (D3D12_RESOURCE_BARRIER) {
474  .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
475  .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
476  .Transition = {
477  .pResource = resource,
478  .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
479  .StateBefore = D3D12_RESOURCE_STATE_COMMON,
480  .StateAfter = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE,
481  },
482  };
483 
484  memset(ctx->ref_subresources, 0, sizeof(UINT) * ctx->max_num_ref);
485  input_args.ReferenceFrames.NumTexture2Ds = ctx->max_num_ref;
486  input_args.ReferenceFrames.ppTexture2Ds = ctx->ref_resources;
487  input_args.ReferenceFrames.pSubresources = ctx->ref_subresources;
488 
489  ret = d3d12va_fence_completion(&f->sync_ctx);
490  if (ret < 0)
491  goto fail;
492 
493  if (!qm)
494  input_args.NumFrameArguments = 1;
495 
496  ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
497  if (ret < 0)
498  goto fail;
499 
500  ret = update_input_arguments(avctx, &input_args, buffer);
501  if (ret < 0)
502  goto fail;
503 
504  DX_CHECK(ID3D12CommandAllocator_Reset(command_allocator));
505 
506  DX_CHECK(ID3D12VideoDecodeCommandList_Reset(cmd_list, command_allocator));
507 
508  num_barrier += d3d12va_update_reference_frames_state(avctx, &barriers[1], resource, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VIDEO_DECODE_READ);
509 
510  ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
511 
512  ID3D12VideoDecodeCommandList_DecodeFrame(cmd_list, ctx->decoder, &output_args, &input_args);
513 
514  for (int i = 0; i < num_barrier; i++)
515  FFSWAP(D3D12_RESOURCE_STATES, barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);
516 
517  ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
518 
519  DX_CHECK(ID3D12VideoDecodeCommandList_Close(cmd_list));
520 
521  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
522 
523  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, f->sync_ctx.fence, ++f->sync_ctx.fence_value));
524 
525  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
526 
527  ret = d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
528  if (ret < 0)
529  return ret;
530 
531  return 0;
532 
533 fail:
534  if (command_allocator)
535  d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
536  return AVERROR(EINVAL);
537 }
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
AVCodecContext::hwaccel
const struct AVHWAccel * hwaccel
Hardware accelerator in use.
Definition: avcodec.h:1427
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
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
HelperObjects
Definition: d3d12va_decode.c:38
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:197
av_fifo_peek
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
Definition: fifo.c:255
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
D3D12VA_VIDEO_DEC_ASYNC_DEPTH
#define D3D12VA_VIDEO_DEC_ASYNC_DEPTH
Definition: d3d12va_decode.h:127
bufref_free_interface
static void bufref_free_interface(void *opaque, uint8_t *data)
Definition: d3d12va_decode.c:170
data
const char data[16]
Definition: mxf.c:148
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:478
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ff_d3d12va_get_surface_index
unsigned ff_d3d12va_get_surface_index(const AVCodecContext *avctx, D3D12VADecodeContext *ctx, const AVFrame *frame, int curr)
Definition: d3d12va_decode.c:50
ff_d3d12va_decode_uninit
int ff_d3d12va_decode_uninit(AVCodecContext *avctx)
uninit D3D12VADecodeContext
Definition: d3d12va_decode.c:373
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:217
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:560
fail
#define fail()
Definition: checkasm.h:179
av_fifo_write
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition: fifo.c:188
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:633
AVRational::num
int num
Numerator.
Definition: rational.h:59
d3d12va_get_valid_helper_objects
static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator, ID3D12Resource **ppBuffer)
Definition: d3d12va_decode.c:87
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
d3d12va_sync_with_gpu
static int d3d12va_sync_with_gpu(AVCodecContext *avctx)
Definition: d3d12va_decode.c:180
av_fifo_read
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition: fifo.c:240
d3d12va_fence_completion
static int d3d12va_fence_completion(AVD3D12VASyncContext *psync_ctx)
Definition: d3d12va_decode.c:157
AVHWFramesContext::height
int height
Definition: hwcontext.h:217
D3D12_OBJECT_RELEASE
#define D3D12_OBJECT_RELEASE(pInterface)
A release macro used by D3D12 objects highly frequently.
Definition: hwcontext_d3d12va_internal.h:51
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_d3d12va_common_frame_params
int ff_d3d12va_common_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
d3d12va common frame params
Definition: d3d12va_decode.c:271
decode.h
AVD3D12VASyncContext
This struct is used to sync d3d12 execution.
Definition: hwcontext_d3d12va.h:84
AVD3D12VASyncContext::fence
ID3D12Fence * fence
D3D12 fence object.
Definition: hwcontext_d3d12va.h:88
ff_decode_get_hw_frames_ctx
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, enum AVHWDeviceType dev_type)
Make sure avctx.hw_frames_ctx is set.
Definition: decode.c:1066
dxva2_internal.h
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:210
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
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
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:495
ff_d3d12va_common_end_frame
int ff_d3d12va_common_end_frame(AVCodecContext *avctx, AVFrame *frame, const void *pp, unsigned pp_size, const void *qm, unsigned qm_size, int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
d3d12va common end frame
Definition: d3d12va_decode.c:434
time.h
AVD3D12VAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_d3d12va.h:126
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
hwcontext_d3d12va.h
D3D12VA_DECODE_CONTEXT
#define D3D12VA_DECODE_CONTEXT(avctx)
Definition: d3d12va_decode.h:128
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
HelperObjects::buffer
ID3D12Resource * buffer
Definition: d3d12va_decode.c:40
AVD3D12VADeviceContext::video_device
ID3D12VideoDevice * video_device
If unset, this will be set from the device field on init.
Definition: hwcontext_d3d12va.h:62
f
f
Definition: af_crystalizer.c:121
AV_HWDEVICE_TYPE_D3D12VA
@ AV_HWDEVICE_TYPE_D3D12VA
Definition: hwcontext.h:40
D3D12VA_FRAMES_CONTEXT
#define D3D12VA_FRAMES_CONTEXT(avctx)
Definition: d3d12va_decode.h:129
d3d12va_create_decoder_heap
static int d3d12va_create_decoder_heap(AVCodecContext *avctx)
Definition: d3d12va_decode.c:191
HelperObjects::command_allocator
ID3D12CommandAllocator * command_allocator
Definition: d3d12va_decode.c:39
ff_d3d12va_get_suitable_max_bitstream_size
int ff_d3d12va_get_suitable_max_bitstream_size(AVCodecContext *avctx)
Get a suitable maximum bitstream size.
Definition: d3d12va_decode.c:44
av_image_get_buffer_size
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters.
Definition: imgutils.c:466
AVD3D12VAFrame
D3D12VA frame descriptor for pool allocation.
Definition: hwcontext_d3d12va.h:106
AVD3D12VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d12va.h:43
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
bufref_wrap_interface
static AVBufferRef * bufref_wrap_interface(IUnknown *iface)
Definition: d3d12va_decode.c:175
common.h
AVCodecContext::height
int height
Definition: avcodec.h:618
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
avcodec.h
AVD3D12VAFramesContext::format
DXGI_FORMAT format
DXGI_FORMAT format.
Definition: hwcontext_d3d12va.h:131
d3d12va_discard_helper_objects
static int d3d12va_discard_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator, ID3D12Resource *pBuffer, uint64_t fence_value)
Definition: d3d12va_decode.c:137
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
frame
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 the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:134
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
av_fifo_alloc2
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition: fifo.c:47
AVCodecContext
main external API structure.
Definition: avcodec.h:445
AVD3D12VASyncContext::event
HANDLE event
A handle to the event object that's raised when the fence reaches a certain value.
Definition: hwcontext_d3d12va.h:94
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
AVRational::den
int den
Denominator.
Definition: rational.h:60
d3d12va_update_reference_frames_state
static int d3d12va_update_reference_frames_state(AVCodecContext *avctx, D3D12_RESOURCE_BARRIER *barriers, ID3D12Resource *current_resource, int state_before, int state_end)
Definition: d3d12va_decode.c:411
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:528
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:633
desc
const char * desc
Definition: libsvtav1.c:79
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
D3D12VADecodeContext
This structure is used to provide the necessary configurations and data to the FFmpeg Direct3D 12 HWA...
Definition: d3d12va_decode.h:37
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
imgutils.h
DX_CHECK
#define DX_CHECK(hr)
A check macro used by D3D12 functions highly frequently.
Definition: hwcontext_d3d12va_internal.h:40
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
update_input_arguments
static int update_input_arguments(AVCodecContext *avctx, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *input_args, ID3D12Resource *buffer)
Definition: d3d12va_av1.c:110
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:664
AVD3D12VASyncContext::fence_value
uint64_t fence_value
The fence value used for sync.
Definition: hwcontext_d3d12va.h:99
hwcontext_d3d12va_internal.h
ff_d3d12va_decode_init
int ff_d3d12va_decode_init(AVCodecContext *avctx)
init D3D12VADecodeContext
Definition: d3d12va_decode.c:283
AVHWAccel::pix_fmt
enum AVPixelFormat pix_fmt
Supported pixel format.
Definition: avcodec.h:2115
d3d12va_decode.h
AV_FIFO_FLAG_AUTO_GROW
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition: fifo.h:63
d3d12va_create_decoder
static int d3d12va_create_decoder(AVCodecContext *avctx)
Definition: d3d12va_decode.c:223
HelperObjects::fence_value
uint64_t fence_value
Definition: d3d12va_decode.c:41