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/time.h"
29 #include "libavutil/imgutils.h"
32 #include "avcodec.h"
33 #include "decode.h"
34 #include "d3d12va_decode.h"
35 #include "dxva2_internal.h"
36 
37 typedef struct HelperObjects {
38  ID3D12CommandAllocator *command_allocator;
39  ID3D12Resource *buffer;
40  uint64_t fence_value;
42 
44 {
45  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
46  return av_image_get_buffer_size(frames_ctx->sw_format, avctx->coded_width, avctx->coded_height, 1);
47 }
48 
51  int curr)
52 {
54  ID3D12Resource *res;
55  unsigned i;
56 
57  f = (AVD3D12VAFrame *)frame->data[0];
58  if (!f)
59  goto fail;
60 
61  res = f->texture;
62  if (!res)
63  goto fail;
64 
65  for (i = 0; i < ctx->max_num_ref; i++) {
66  if (ctx->ref_resources[i] && res == ctx->ref_resources[i]) {
67  ctx->used_mask |= 1 << i;
68  return i;
69  }
70  }
71 
72  if (curr) {
73  for (i = 0; i < ctx->max_num_ref; i++) {
74  if (!((ctx->used_mask >> i) & 0x1)) {
75  ctx->ref_resources[i] = res;
76  return i;
77  }
78  }
79  }
80 
81 fail:
82  av_log((AVCodecContext *)avctx, AV_LOG_WARNING, "Could not get surface index. Using 0 instead.\n");
83  return 0;
84 }
85 
86 static int d3d12va_get_valid_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator,
87  ID3D12Resource **ppBuffer)
88 {
89  HRESULT hr;
91  HelperObjects obj = { 0 };
92  D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
93 
94  D3D12_RESOURCE_DESC desc = {
95  .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
96  .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
97  .Width = ctx->bitstream_size,
98  .Height = 1,
99  .DepthOrArraySize = 1,
100  .MipLevels = 1,
101  .Format = DXGI_FORMAT_UNKNOWN,
102  .SampleDesc = { .Count = 1, .Quality = 0 },
103  .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
104  .Flags = D3D12_RESOURCE_FLAG_NONE,
105  };
106 
107  if (av_fifo_peek(ctx->objects_queue, &obj, 1, 0) >= 0) {
108  uint64_t completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
109  if (completion >= obj.fence_value) {
110  *ppAllocator = obj.command_allocator;
111  *ppBuffer = obj.buffer;
112  av_fifo_read(ctx->objects_queue, &obj, 1);
113  return 0;
114  }
115  }
116 
117  hr = ID3D12Device_CreateCommandAllocator(ctx->device_ctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
118  &IID_ID3D12CommandAllocator, (void **)ppAllocator);
119  if (FAILED(hr)) {
120  av_log(avctx, AV_LOG_ERROR, "Failed to create a new command allocator!\n");
121  return AVERROR(EINVAL);
122  }
123 
124  hr = ID3D12Device_CreateCommittedResource(ctx->device_ctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
125  &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
126  &IID_ID3D12Resource, (void **)ppBuffer);
127 
128  if (FAILED(hr)) {
129  av_log(avctx, AV_LOG_ERROR, "Failed to create a new d3d12 buffer!\n");
130  return AVERROR(EINVAL);
131  }
132 
133  return 0;
134 }
135 
136 static int d3d12va_discard_helper_objects(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator,
137  ID3D12Resource *pBuffer, uint64_t fence_value)
138 {
140 
141  HelperObjects obj = {
142  .command_allocator = pAllocator,
143  .buffer = pBuffer,
144  .fence_value = fence_value,
145  };
146 
147  if (av_fifo_write(ctx->objects_queue, &obj, 1) < 0) {
148  D3D12_OBJECT_RELEASE(pAllocator);
149  D3D12_OBJECT_RELEASE(pBuffer);
150  return AVERROR(ENOMEM);
151  }
152 
153  return 0;
154 }
155 
157 {
158  uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->fence);
159  if (completion < psync_ctx->fence_value) {
160  if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->fence, psync_ctx->fence_value, psync_ctx->event)))
161  return AVERROR(EINVAL);
162 
163  WaitForSingleObjectEx(psync_ctx->event, INFINITE, FALSE);
164  }
165 
166  return 0;
167 }
168 
169 static void bufref_free_interface(void *opaque, uint8_t *data)
170 {
171  D3D12_OBJECT_RELEASE(opaque);
172 }
173 
174 static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
175 {
176  return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
177 }
178 
180 {
182 
183  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
184  return d3d12va_fence_completion(&ctx->sync_ctx);
185 
186 fail:
187  return AVERROR(EINVAL);
188 }
189 
191 {
193  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
194  AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx;
195  AVD3D12VAFramesContext *frames_hwctx = frames_ctx->hwctx;
196 
197  D3D12_VIDEO_DECODER_HEAP_DESC desc = {
198  .NodeMask = 0,
199  .Configuration = ctx->cfg,
200  .DecodeWidth = frames_ctx->width,
201  .DecodeHeight = frames_ctx->height,
202  .Format = frames_hwctx->format,
203  .FrameRate = { avctx->framerate.num, avctx->framerate.den },
204  .BitRate = avctx->bit_rate,
205  .MaxDecodePictureBufferCount = ctx->max_num_ref,
206  };
207 
208  DX_CHECK(ID3D12VideoDevice_CreateVideoDecoderHeap(device_hwctx->video_device, &desc,
209  &IID_ID3D12VideoDecoderHeap, (void **)&ctx->decoder_heap));
210 
211  return 0;
212 
213 fail:
214  if (ctx->decoder) {
215  av_log(avctx, AV_LOG_ERROR, "D3D12 doesn't support decoding frames with an extent "
216  "[width(%d), height(%d)], on your device!\n", frames_ctx->width, frames_ctx->height);
217  }
218 
219  return AVERROR(EINVAL);
220 }
221 
223 {
224  D3D12_VIDEO_DECODER_DESC desc;
226  AVHWFramesContext *frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
227  AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx;
228  AVD3D12VAFramesContext *frames_hwctx = frames_ctx->hwctx;
229 
230  D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT feature = {
231  .NodeIndex = 0,
232  .Configuration = ctx->cfg,
233  .Width = frames_ctx->width,
234  .Height = frames_ctx->height,
235  .DecodeFormat = frames_hwctx->format,
236  .FrameRate = { avctx->framerate.num, avctx->framerate.den },
237  .BitRate = avctx->bit_rate,
238  };
239 
240  DX_CHECK(ID3D12VideoDevice_CheckFeatureSupport(device_hwctx->video_device, D3D12_FEATURE_VIDEO_DECODE_SUPPORT,
241  &feature, sizeof(feature)));
242  if (!(feature.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED)) {
243  av_log(avctx, AV_LOG_ERROR, "D3D12 video decode is not supported on this device.\n");
244  return AVERROR(ENOSYS);
245  }
246  if (!(feature.DecodeTier >= D3D12_VIDEO_DECODE_TIER_2)) {
247  av_log(avctx, AV_LOG_ERROR, "D3D12 video decode on this device requires tier %d support, "
248  "but it is not implemented.\n", feature.DecodeTier);
249  return AVERROR_PATCHWELCOME;
250  }
251 
252  desc = (D3D12_VIDEO_DECODER_DESC) {
253  .NodeMask = 0,
254  .Configuration = ctx->cfg,
255  };
256 
257  DX_CHECK(ID3D12VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc, &IID_ID3D12VideoDecoder,
258  (void **)&ctx->decoder));
259 
260  ctx->decoder_ref = bufref_wrap_interface((IUnknown *)ctx->decoder);
261  if (!ctx->decoder_ref)
262  return AVERROR(ENOMEM);
263 
264  return 0;
265 
266 fail:
267  return AVERROR(EINVAL);
268 }
269 
271 {
272  AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data;
273 
274  frames_ctx->format = AV_PIX_FMT_D3D12;
276  frames_ctx->width = avctx->width;
277  frames_ctx->height = avctx->height;
278 
279  return 0;
280 }
281 
283 {
284  int ret;
285  AVHWFramesContext *frames_ctx;
287  ID3D12Resource *buffer = NULL;
288  ID3D12CommandAllocator *command_allocator = NULL;
289  D3D12_COMMAND_QUEUE_DESC queue_desc = {
290  .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE,
291  .Priority = 0,
292  .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
293  .NodeMask = 0,
294  };
295 
296  ctx->pix_fmt = avctx->hwaccel->pix_fmt;
297 
299  if (ret < 0)
300  return ret;
301 
302  frames_ctx = D3D12VA_FRAMES_CONTEXT(avctx);
303  ctx->device_ctx = (AVD3D12VADeviceContext *)frames_ctx->device_ctx->hwctx;
304 
305  if (frames_ctx->format != ctx->pix_fmt) {
306  av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n");
307  goto fail;
308  }
309 
310  ret = d3d12va_create_decoder(avctx);
311  if (ret < 0)
312  goto fail;
313 
315  if (ret < 0)
316  goto fail;
317 
318  ctx->bitstream_size = ff_d3d12va_get_suitable_max_bitstream_size(avctx);
319 
320  ctx->ref_resources = av_calloc(ctx->max_num_ref, sizeof(*ctx->ref_resources));
321  if (!ctx->ref_resources)
322  return AVERROR(ENOMEM);
323 
324  ctx->ref_subresources = av_calloc(ctx->max_num_ref, sizeof(*ctx->ref_subresources));
325  if (!ctx->ref_subresources)
326  return AVERROR(ENOMEM);
327 
330  if (!ctx->objects_queue)
331  return AVERROR(ENOMEM);
332 
333  DX_CHECK(ID3D12Device_CreateFence(ctx->device_ctx->device, 0, D3D12_FENCE_FLAG_NONE,
334  &IID_ID3D12Fence, (void **)&ctx->sync_ctx.fence));
335 
336  ctx->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
337  if (!ctx->sync_ctx.event)
338  goto fail;
339 
340  ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
341  if (ret < 0)
342  goto fail;
343 
344  DX_CHECK(ID3D12Device_CreateCommandQueue(ctx->device_ctx->device, &queue_desc,
345  &IID_ID3D12CommandQueue, (void **)&ctx->command_queue));
346 
347  DX_CHECK(ID3D12Device_CreateCommandList(ctx->device_ctx->device, 0, queue_desc.Type,
348  command_allocator, NULL, &IID_ID3D12CommandList, (void **)&ctx->command_list));
349 
350  DX_CHECK(ID3D12VideoDecodeCommandList_Close(ctx->command_list));
351 
352  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
353 
354  ret = d3d12va_sync_with_gpu(avctx);
355  if (ret < 0)
356  goto fail;
357 
358  d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
359  if (ret < 0)
360  goto fail;
361 
362  return 0;
363 
364 fail:
365  D3D12_OBJECT_RELEASE(command_allocator);
368 
369  return AVERROR(EINVAL);
370 }
371 
373 {
374  int num_allocator = 0;
376  HelperObjects obj;
377 
378  if (ctx->sync_ctx.fence)
379  d3d12va_sync_with_gpu(avctx);
380 
381  av_freep(&ctx->ref_resources);
382  av_freep(&ctx->ref_subresources);
383 
384  D3D12_OBJECT_RELEASE(ctx->command_list);
385  D3D12_OBJECT_RELEASE(ctx->command_queue);
386 
387  if (ctx->objects_queue) {
388  while (av_fifo_read(ctx->objects_queue, &obj, 1) >= 0) {
389  num_allocator++;
392  }
393 
394  av_log(avctx, AV_LOG_VERBOSE, "Total number of command allocators reused: %d\n", num_allocator);
395  }
396 
397  av_fifo_freep2(&ctx->objects_queue);
398 
399  D3D12_OBJECT_RELEASE(ctx->sync_ctx.fence);
400  if (ctx->sync_ctx.event)
401  CloseHandle(ctx->sync_ctx.event);
402 
403  D3D12_OBJECT_RELEASE(ctx->decoder_heap);
404 
405  av_buffer_unref(&ctx->decoder_ref);
406 
407  return 0;
408 }
409 
410 static inline int d3d12va_update_reference_frames_state(AVCodecContext *avctx, D3D12_RESOURCE_BARRIER *barriers,
411  ID3D12Resource *current_resource, int state_before, int state_end)
412 {
414 
415  int num_barrier = 0;
416  for (int i = 0; i < ctx->max_num_ref; i++) {
417  if (((ctx->used_mask >> i) & 0x1) && ctx->ref_resources[i] && ctx->ref_resources[i] != current_resource) {
418  barriers[num_barrier].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
419  barriers[num_barrier].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
420  barriers[num_barrier].Transition = (D3D12_RESOURCE_TRANSITION_BARRIER){
421  .pResource = ctx->ref_resources[i],
422  .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
423  .StateBefore = state_before,
424  .StateAfter = state_end,
425  };
426  num_barrier++;
427  }
428  }
429 
430  return num_barrier;
431 }
432 
434  const void *pp, unsigned pp_size,
435  const void *qm, unsigned qm_size,
436  int(*update_input_arguments)(AVCodecContext *, D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS *, ID3D12Resource *))
437 {
438  int ret;
440  ID3D12Resource *buffer = NULL;
441  ID3D12CommandAllocator *command_allocator = NULL;
443  ID3D12Resource *resource = (ID3D12Resource *)f->texture;
444 
445  ID3D12VideoDecodeCommandList *cmd_list = ctx->command_list;
446  D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
447 
448  D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS input_args = {
449  .NumFrameArguments = 2,
450  .FrameArguments = {
451  [0] = {
452  .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_PICTURE_PARAMETERS,
453  .Size = pp_size,
454  .pData = (void *)pp,
455  },
456  [1] = {
457  .Type = D3D12_VIDEO_DECODE_ARGUMENT_TYPE_INVERSE_QUANTIZATION_MATRIX,
458  .Size = qm_size,
459  .pData = (void *)qm,
460  },
461  },
462  .pHeap = ctx->decoder_heap,
463  };
464 
465  D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS output_args = {
466  .ConversionArguments = { 0 },
467  .OutputSubresource = 0,
468  .pOutputTexture2D = resource,
469  };
470 
471  UINT num_barrier = 1;
472  barriers[0] = (D3D12_RESOURCE_BARRIER) {
473  .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
474  .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
475  .Transition = {
476  .pResource = resource,
477  .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
478  .StateBefore = D3D12_RESOURCE_STATE_COMMON,
479  .StateAfter = D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE,
480  },
481  };
482 
483  memset(ctx->ref_subresources, 0, sizeof(UINT) * ctx->max_num_ref);
484  input_args.ReferenceFrames.NumTexture2Ds = ctx->max_num_ref;
485  input_args.ReferenceFrames.ppTexture2Ds = ctx->ref_resources;
486  input_args.ReferenceFrames.pSubresources = ctx->ref_subresources;
487 
488  ret = d3d12va_fence_completion(&f->sync_ctx);
489  if (ret < 0)
490  goto fail;
491 
492  if (!qm)
493  input_args.NumFrameArguments = 1;
494 
495  ret = d3d12va_get_valid_helper_objects(avctx, &command_allocator, &buffer);
496  if (ret < 0)
497  goto fail;
498 
499  ret = update_input_arguments(avctx, &input_args, buffer);
500  if (ret < 0)
501  goto fail;
502 
503  DX_CHECK(ID3D12CommandAllocator_Reset(command_allocator));
504 
505  DX_CHECK(ID3D12VideoDecodeCommandList_Reset(cmd_list, command_allocator));
506 
507  num_barrier += d3d12va_update_reference_frames_state(avctx, &barriers[1], resource, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VIDEO_DECODE_READ);
508 
509  ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
510 
511  ID3D12VideoDecodeCommandList_DecodeFrame(cmd_list, ctx->decoder, &output_args, &input_args);
512 
513  for (int i = 0; i < num_barrier; i++)
514  FFSWAP(D3D12_RESOURCE_STATES, barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter);
515 
516  ID3D12VideoDecodeCommandList_ResourceBarrier(cmd_list, num_barrier, barriers);
517 
518  DX_CHECK(ID3D12VideoDecodeCommandList_Close(cmd_list));
519 
520  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
521 
522  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, f->sync_ctx.fence, ++f->sync_ctx.fence_value));
523 
524  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
525 
526  ret = d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
527  if (ret < 0)
528  return ret;
529 
530  return 0;
531 
532 fail:
533  if (command_allocator)
534  d3d12va_discard_helper_objects(avctx, command_allocator, buffer, ctx->sync_ctx.fence_value);
535  return AVERROR(EINVAL);
536 }
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:37
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:344
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:169
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:49
ff_d3d12va_decode_uninit
int ff_d3d12va_decode_uninit(AVCodecContext *avctx)
uninit D3D12VADecodeContext
Definition: d3d12va_decode.c:372
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:217
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:365
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:86
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:179
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:156
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:48
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:270
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:1064
frame
static AVFrame * frame
Definition: demux_decode.c:54
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:433
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:39
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:190
HelperObjects::command_allocator
ID3D12CommandAllocator * command_allocator
Definition: d3d12va_decode.c:38
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:43
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:255
bufref_wrap_interface
static AVBufferRef * bufref_wrap_interface(IUnknown *iface)
Definition: d3d12va_decode.c:174
common.h
AVCodecContext::height
int height
Definition: avcodec.h:618
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
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:136
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
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:410
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:75
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:109
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:282
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:67
d3d12va_create_decoder
static int d3d12va_create_decoder(AVCodecContext *avctx)
Definition: d3d12va_decode.c:222
HelperObjects::fence_value
uint64_t fence_value
Definition: d3d12va_decode.c:40