FFmpeg
d3d12va_encode.c
Go to the documentation of this file.
1 /*
2  * Direct3D 12 HW acceleration video encoder
3  *
4  * Copyright (c) 2024 Intel Corporation
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 "libavutil/avassert.h"
24 #include "libavutil/common.h"
25 #include "libavutil/internal.h"
26 #include "libavutil/log.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/pixdesc.h"
31 
32 #include "config_components.h"
33 #include "avcodec.h"
34 #include "d3d12va_encode.h"
35 #include "encode.h"
36 
38  HW_CONFIG_ENCODER_FRAMES(D3D12, D3D12VA),
39  NULL,
40 };
41 
43 {
44  uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->fence);
45  if (completion < psync_ctx->fence_value) {
46  if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->fence, psync_ctx->fence_value, psync_ctx->event)))
47  return AVERROR(EINVAL);
48 
49  WaitForSingleObjectEx(psync_ctx->event, INFINITE, FALSE);
50  }
51 
52  return 0;
53 }
54 
56 {
58 
59  DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
60  return d3d12va_fence_completion(&ctx->sync_ctx);
61 
62 fail:
63  return AVERROR(EINVAL);
64 }
65 
66 typedef struct CommandAllocator {
67  ID3D12CommandAllocator *command_allocator;
68  uint64_t fence_value;
70 
71 static int d3d12va_get_valid_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator)
72 {
73  HRESULT hr;
75  CommandAllocator allocator;
76 
77  if (av_fifo_peek(ctx->allocator_queue, &allocator, 1, 0) >= 0) {
78  uint64_t completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
79  if (completion >= allocator.fence_value) {
80  *ppAllocator = allocator.command_allocator;
81  av_fifo_read(ctx->allocator_queue, &allocator, 1);
82  return 0;
83  }
84  }
85 
86  hr = ID3D12Device_CreateCommandAllocator(ctx->hwctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
87  &IID_ID3D12CommandAllocator, (void **)ppAllocator);
88  if (FAILED(hr)) {
89  av_log(avctx, AV_LOG_ERROR, "Failed to create a new command allocator!\n");
90  return AVERROR(EINVAL);
91  }
92 
93  return 0;
94 }
95 
96 static int d3d12va_discard_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator, uint64_t fence_value)
97 {
99 
100  CommandAllocator allocator = {
101  .command_allocator = pAllocator,
102  .fence_value = fence_value,
103  };
104 
105  av_fifo_write(ctx->allocator_queue, &allocator, 1);
106 
107  return 0;
108 }
109 
111  FFHWBaseEncodePicture *base_pic)
112 {
114  D3D12VAEncodePicture *pic = base_pic->priv;
115  uint64_t completion;
116 
117  av_assert0(base_pic->encode_issued);
118 
119  if (base_pic->encode_complete) {
120  // Already waited for this picture.
121  return 0;
122  }
123 
124  completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
125  if (completion < pic->fence_value) {
126  if (FAILED(ID3D12Fence_SetEventOnCompletion(ctx->sync_ctx.fence, pic->fence_value,
127  ctx->sync_ctx.event)))
128  return AVERROR(EINVAL);
129 
130  WaitForSingleObjectEx(ctx->sync_ctx.event, INFINITE, FALSE);
131  }
132 
133  av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" "
134  "(input surface %p).\n", base_pic->display_order,
135  base_pic->encode_order, pic->input_surface->texture);
136 
137  av_frame_free(&base_pic->input_image);
138 
139  base_pic->encode_complete = 1;
140  return 0;
141 }
142 
145 {
147  int width = sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) + sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA);
148 #if CONFIG_AV1_D3D12VA_ENCODER
149  if (ctx->codec->d3d12_codec == D3D12_VIDEO_ENCODER_CODEC_AV1) {
150  width += sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES)
151  + sizeof(D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES);
152  }
153 #endif
154  D3D12_HEAP_PROPERTIES encoded_meta_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }, resolved_meta_props;
155  D3D12_HEAP_TYPE resolved_heap_type = D3D12_HEAP_TYPE_READBACK;
156  HRESULT hr;
157 
158  D3D12_RESOURCE_DESC meta_desc = {
159  .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
160  .Alignment = 0,
161  .Width = ctx->req.MaxEncoderOutputMetadataBufferSize,
162  .Height = 1,
163  .DepthOrArraySize = 1,
164  .MipLevels = 1,
165  .Format = DXGI_FORMAT_UNKNOWN,
166  .SampleDesc = { .Count = 1, .Quality = 0 },
167  .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
168  .Flags = D3D12_RESOURCE_FLAG_NONE,
169  };
170 
171  hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &encoded_meta_props, D3D12_HEAP_FLAG_NONE,
172  &meta_desc, D3D12_RESOURCE_STATE_COMMON, NULL,
173  &IID_ID3D12Resource, (void **)&pic->encoded_metadata);
174  if (FAILED(hr)) {
175  av_log(avctx, AV_LOG_ERROR, "Failed to create metadata buffer.\n");
176  return AVERROR_UNKNOWN;
177  }
178 
179  ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(ctx->hwctx->device, &resolved_meta_props, 0, resolved_heap_type);
180 
181  meta_desc.Width = width;
182 
183  hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &resolved_meta_props, D3D12_HEAP_FLAG_NONE,
184  &meta_desc, D3D12_RESOURCE_STATE_COMMON, NULL,
185  &IID_ID3D12Resource, (void **)&pic->resolved_metadata);
186 
187  if (FAILED(hr)) {
188  av_log(avctx, AV_LOG_ERROR, "Failed to create output metadata buffer.\n");
189  return AVERROR_UNKNOWN;
190  }
191 
192  return 0;
193 }
194 
196  FFHWBaseEncodePicture *base_pic)
197 {
198  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
200  D3D12VAEncodePicture *pic = base_pic->priv;
201  AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
202  int err, i, j;
203  HRESULT hr;
205  void *ptr;
206  size_t bit_len;
207  ID3D12CommandAllocator *command_allocator = NULL;
208  ID3D12VideoEncodeCommandList2 *cmd_list = ctx->command_list;
209  D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
210  D3D12_VIDEO_ENCODE_REFERENCE_FRAMES d3d12_refs = { 0 };
211  int barriers_ref_index = 0;
212  D3D12_RESOURCE_BARRIER *barriers_ref = NULL;
213 
214  D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
215  .SequenceControlDesc = {
216  .Flags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE,
217  .IntraRefreshConfig = { 0 },
218  .RateControl = ctx->rc,
219  .PictureTargetResolution = ctx->resolution,
220  .SelectedLayoutMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
221  .FrameSubregionsLayoutData = ctx->subregions_layout,
222  .CodecGopSequence = ctx->gop,
223  },
224  .pInputFrame = pic->input_surface->texture,
225  .InputFrameSubresource = 0,
226  };
227 
228  D3D12_VIDEO_ENCODER_ENCODEFRAME_OUTPUT_ARGUMENTS output_args = { 0 };
229 
230  D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS input_metadata = {
231  .EncoderCodec = ctx->codec->d3d12_codec,
232  .EncoderProfile = ctx->profile->d3d12_profile,
233  .EncoderInputFormat = frames_hwctx->format,
234  .EncodedPictureEffectiveResolution = ctx->resolution,
235  };
236 
237  D3D12_VIDEO_ENCODER_RESOLVE_METADATA_OUTPUT_ARGUMENTS output_metadata = { 0 };
238 
239  memset(data, 0, sizeof(data));
240 
241  av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
242  "as type %s.\n", base_pic->display_order, base_pic->encode_order,
244  if (base_pic->nb_refs[0] == 0 && base_pic->nb_refs[1] == 0) {
245  av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
246  } else {
247  av_log(avctx, AV_LOG_DEBUG, "L0 refers to");
248  for (i = 0; i < base_pic->nb_refs[0]; i++) {
249  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
250  base_pic->refs[0][i]->display_order, base_pic->refs[0][i]->encode_order);
251  }
252  av_log(avctx, AV_LOG_DEBUG, ".\n");
253 
254  if (base_pic->nb_refs[1]) {
255  av_log(avctx, AV_LOG_DEBUG, "L1 refers to");
256  for (i = 0; i < base_pic->nb_refs[1]; i++) {
257  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
258  base_pic->refs[1][i]->display_order, base_pic->refs[1][i]->encode_order);
259  }
260  av_log(avctx, AV_LOG_DEBUG, ".\n");
261  }
262  }
263 
264  av_assert0(!base_pic->encode_issued);
265  for (i = 0; i < base_pic->nb_refs[0]; i++) {
266  av_assert0(base_pic->refs[0][i]);
267  av_assert0(base_pic->refs[0][i]->encode_issued);
268  }
269  for (i = 0; i < base_pic->nb_refs[1]; i++) {
270  av_assert0(base_pic->refs[1][i]);
271  av_assert0(base_pic->refs[1][i]->encode_issued);
272  }
273 
274  av_log(avctx, AV_LOG_DEBUG, "Input surface is %p.\n", pic->input_surface->texture);
275 
276  pic->recon_surface = (AVD3D12VAFrame *)base_pic->recon_image->data[0];
277  av_log(avctx, AV_LOG_DEBUG, "Recon surface is %p.\n",
278  pic->recon_surface->texture);
279 
280  pic->subresource_index = ctx->is_texture_array ? pic->recon_surface->subresource_index : 0;
281 
282  pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
283  if (!pic->output_buffer_ref) {
284  err = AVERROR(ENOMEM);
285  goto fail;
286  }
287  pic->output_buffer = (ID3D12Resource *)pic->output_buffer_ref->data;
288  av_log(avctx, AV_LOG_DEBUG, "Output buffer is %p.\n",
289  pic->output_buffer);
290 
291  err = d3d12va_encode_create_metadata_buffers(avctx, pic);
292  if (err < 0)
293  goto fail;
294 
295  if (ctx->codec->init_picture_params) {
296  err = ctx->codec->init_picture_params(avctx, base_pic);
297  if (err < 0) {
298  av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
299  "parameters: %d.\n", err);
300  goto fail;
301  }
302  }
303 
304  if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
305  if (ctx->codec->write_sequence_header) {
306  bit_len = 8 * sizeof(data);
307  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
308  if (err < 0) {
309  av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
310  "header: %d.\n", err);
311  goto fail;
312  }
313  pic->header_size = (int)bit_len / 8;
314  pic->aligned_header_size = pic->header_size % ctx->req.CompressedBitstreamBufferAccessAlignment ?
315  FFALIGN(pic->header_size, ctx->req.CompressedBitstreamBufferAccessAlignment) :
316  pic->header_size;
317 
318  hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&ptr);
319  if (FAILED(hr)) {
320  err = AVERROR_UNKNOWN;
321  goto fail;
322  }
323 
324  memcpy(ptr, data, pic->aligned_header_size);
325  ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
326  }
327  }
328 
329  d3d12_refs.NumTexture2Ds = base_pic->nb_refs[0] + base_pic->nb_refs[1];
330  if (d3d12_refs.NumTexture2Ds) {
331  d3d12_refs.ppTexture2Ds = av_calloc(d3d12_refs.NumTexture2Ds,
332  sizeof(*d3d12_refs.ppTexture2Ds));
333  if (!d3d12_refs.ppTexture2Ds) {
334  err = AVERROR(ENOMEM);
335  goto fail;
336  }
337 
338  if (ctx->is_texture_array) {
339  d3d12_refs.pSubresources = av_calloc(d3d12_refs.NumTexture2Ds,
340  sizeof(*d3d12_refs.pSubresources));
341  if (!d3d12_refs.pSubresources) {
342  err = AVERROR(ENOMEM);
343  goto fail;
344  }
345  }
346 
347  i = 0;
348  for (j = 0; j < base_pic->nb_refs[0]; j++) {
349  d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->recon_surface->texture;
350  if (ctx->is_texture_array)
351  d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->subresource_index;
352  i++;
353  }
354  for (j = 0; j < base_pic->nb_refs[1]; j++) {
355  d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->recon_surface->texture;
356  if (ctx->is_texture_array)
357  d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->subresource_index;
358  i++;
359  }
360  }
361 
362  input_args.PictureControlDesc.IntraRefreshFrameIndex = 0;
363  if (base_pic->is_reference)
364  input_args.PictureControlDesc.Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE;
365 
366  input_args.PictureControlDesc.PictureControlCodecData = pic->pic_ctl;
367  input_args.PictureControlDesc.ReferenceFrames = d3d12_refs;
368  input_args.CurrentFrameBitstreamMetadataSize = pic->aligned_header_size;
369 
370  output_args.Bitstream.pBuffer = pic->output_buffer;
371  output_args.Bitstream.FrameStartOffset = pic->aligned_header_size;
372  output_args.ReconstructedPicture.pReconstructedPicture = pic->recon_surface->texture;
373  output_args.ReconstructedPicture.ReconstructedPictureSubresource = ctx->is_texture_array ? pic->subresource_index : 0;
374  output_args.EncoderOutputMetadata.pBuffer = pic->encoded_metadata;
375  output_args.EncoderOutputMetadata.Offset = 0;
376 
377  input_metadata.HWLayoutMetadata.pBuffer = pic->encoded_metadata;
378  input_metadata.HWLayoutMetadata.Offset = 0;
379 
380  output_metadata.ResolvedLayoutMetadata.pBuffer = pic->resolved_metadata;
381  output_metadata.ResolvedLayoutMetadata.Offset = 0;
382 
383  err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
384  if (err < 0)
385  goto fail;
386 
387  hr = ID3D12CommandAllocator_Reset(command_allocator);
388  if (FAILED(hr)) {
389  err = AVERROR_UNKNOWN;
390  goto fail;
391  }
392 
393  hr = ID3D12VideoEncodeCommandList2_Reset(cmd_list, command_allocator);
394  if (FAILED(hr)) {
395  err = AVERROR_UNKNOWN;
396  goto fail;
397  }
398 
399 #define TRANSITION_BARRIER(res, subres, before, after) \
400  (D3D12_RESOURCE_BARRIER) { \
401  .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
402  .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
403  .Transition = { \
404  .pResource = res, \
405  .Subresource = subres, \
406  .StateBefore = before, \
407  .StateAfter = after, \
408  }, \
409  }
410 
411  barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
412  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
413  D3D12_RESOURCE_STATE_COMMON,
414  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
415  barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
416  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
417  D3D12_RESOURCE_STATE_COMMON,
418  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
419  barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
420  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
421  D3D12_RESOURCE_STATE_COMMON,
422  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
423  barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
424  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
425  D3D12_RESOURCE_STATE_COMMON,
426  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
427 
428  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
429 
430  if (ctx->is_texture_array)
431  barriers_ref = av_calloc(base_ctx->recon_frames->initial_pool_size * ctx->plane_count,
432  sizeof(D3D12_RESOURCE_BARRIER));
433  else
434  barriers_ref = av_calloc(MAX_DPB_SIZE, sizeof(D3D12_RESOURCE_BARRIER));
435 
436  if (ctx->is_texture_array) {
437  D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
438  pic->recon_surface->texture->lpVtbl->GetDesc(pic->recon_surface->texture, &references_tex_array_desc);
439 
440  for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
441  reference_subresource++) {
442 
443  uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
444  uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
445  uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
446 
447  for (uint32_t plane_slice = 0; plane_slice < ctx->plane_count; plane_slice++) {
448  uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
449  plane_slice * references_tex_array_desc.MipLevels * array_size;
450  if (reference_subresource == pic->subresource_index) {
451  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
452  D3D12_RESOURCE_STATE_COMMON,
453  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
454  } else {
455  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
456  D3D12_RESOURCE_STATE_COMMON,
457  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
458  }
459  }
460  }
461  } else {
462  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture,
463  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
464  D3D12_RESOURCE_STATE_COMMON,
465  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
466 
467  if (d3d12_refs.NumTexture2Ds) {
468  for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
469  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
470  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
471  D3D12_RESOURCE_STATE_COMMON,
472  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
473  }
474  }
475  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
476 
477  ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list, ctx->encoder, ctx->encoder_heap,
478  &input_args, &output_args);
479 
480  barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
481  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
482  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
483  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
484 
485  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 1, &barriers[3]);
486 
487  ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
488 
489  if (barriers_ref_index > 0) {
490  for (i = 0; i < barriers_ref_index; i++)
491  FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[i].Transition.StateBefore, barriers_ref[i].Transition.StateAfter);
492 
493  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
494  barriers_ref);
495  }
496 
497  barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
498  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
499  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
500  D3D12_RESOURCE_STATE_COMMON);
501  barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
502  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
503  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
504  D3D12_RESOURCE_STATE_COMMON);
505  barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
506  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
507  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
508  D3D12_RESOURCE_STATE_COMMON);
509  barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
510  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
511  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
512  D3D12_RESOURCE_STATE_COMMON);
513 
514  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
515 
516  hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
517  if (FAILED(hr)) {
518  err = AVERROR_UNKNOWN;
519  goto fail;
520  }
521 
522  hr = ID3D12CommandQueue_Wait(ctx->command_queue, pic->input_surface->sync_ctx.fence,
524  if (FAILED(hr)) {
525  err = AVERROR_UNKNOWN;
526  goto fail;
527  }
528 
529  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
530 
531  hr = ID3D12CommandQueue_Signal(ctx->command_queue, pic->input_surface->sync_ctx.fence,
533  if (FAILED(hr)) {
534  err = AVERROR_UNKNOWN;
535  goto fail;
536  }
537 
538  hr = ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value);
539  if (FAILED(hr)) {
540  err = AVERROR_UNKNOWN;
541  goto fail;
542  }
543 
544  err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
545  if (err < 0)
546  goto fail;
547 
548  pic->fence_value = ctx->sync_ctx.fence_value;
549 
550  if (d3d12_refs.ppTexture2Ds)
551  av_freep(&d3d12_refs.ppTexture2Ds);
552 
553  if (ctx->is_texture_array && d3d12_refs.pSubresources)
554  av_freep(&d3d12_refs.pSubresources);
555 
556  if (barriers_ref)
557  av_freep(&barriers_ref);
558 
559  return 0;
560 
561 fail:
562  if (command_allocator)
563  d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
564 
565  if (d3d12_refs.ppTexture2Ds)
566  av_freep(&d3d12_refs.ppTexture2Ds);
567 
568  if (ctx->is_texture_array && d3d12_refs.pSubresources)
569  av_freep(&d3d12_refs.pSubresources);
570 
571  if (barriers_ref)
572  av_freep(&barriers_ref);
573 
574  if (ctx->codec->free_picture_params)
575  ctx->codec->free_picture_params(pic);
576 
578  pic->output_buffer = NULL;
581  return err;
582 }
583 
585  FFHWBaseEncodePicture *base_pic)
586 {
587  D3D12VAEncodePicture *pic = base_pic->priv;
588 
589  d3d12va_encode_wait(avctx, base_pic);
590 
591  if (pic->output_buffer_ref) {
592  av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
593  "%"PRId64"/%"PRId64".\n",
594  base_pic->display_order, base_pic->encode_order);
595 
597  pic->output_buffer = NULL;
598  }
599 
602 
603  return 0;
604 }
605 
607 {
609 
610  switch (ctx->rc.Mode)
611  {
612  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP:
613  av_freep(&ctx->rc.ConfigParams.pConfiguration_CQP);
614  break;
615  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR:
616  av_freep(&ctx->rc.ConfigParams.pConfiguration_CBR);
617  break;
618  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR:
619  av_freep(&ctx->rc.ConfigParams.pConfiguration_VBR);
620  break;
621  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR:
622  av_freep(&ctx->rc.ConfigParams.pConfiguration_QVBR);
623  break;
624  default:
625  break;
626  }
627 
628  return 0;
629 }
630 
632 {
634  D3D12VAEncodePicture *priv = pic->priv;
635  AVFrame *frame = pic->input_image;
636 
637  if (ctx->codec->picture_priv_data_size > 0) {
638  pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
639  if (!pic->codec_priv)
640  return AVERROR(ENOMEM);
641  }
642 
643  priv->input_surface = (AVD3D12VAFrame *)frame->data[0];
644 
645  return 0;
646 }
647 
649 {
651  D3D12VAEncodePicture *priv = pic->priv;
652 
653  if (pic->encode_issued)
654  d3d12va_encode_discard(avctx, pic);
655 
656  if (ctx->codec->free_picture_params)
657  ctx->codec->free_picture_params(priv);
658 
659  return 0;
660 }
661 
663  D3D12VAEncodePicture *pic, size_t *size)
664 {
665  D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta = NULL;
666  uint8_t *data;
667  HRESULT hr;
668  int err;
669 
670  hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
671  if (FAILED(hr)) {
672  err = AVERROR_UNKNOWN;
673  return err;
674  }
675 
676  meta = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)data;
677 
678  if (meta->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
679  av_log(avctx, AV_LOG_ERROR, "Encode failed %"PRIu64"\n", meta->EncodeErrorFlags);
680  err = AVERROR(EINVAL);
681  return err;
682  }
683 
684  if (meta->EncodedBitstreamWrittenBytesCount == 0) {
685  av_log(avctx, AV_LOG_ERROR, "No bytes were written to encoded bitstream\n");
686  err = AVERROR(EINVAL);
687  return err;
688  }
689 
690  *size = meta->EncodedBitstreamWrittenBytesCount;
691 
692  ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
693 
694  return 0;
695 }
696 
699 {
700  int err;
701  uint8_t *ptr, *mapped_data;
702  size_t total_size = 0;
703  HRESULT hr;
704 
705  err = d3d12va_encode_get_buffer_size(avctx, pic, &total_size);
706  if (err < 0)
707  goto end;
708 
709  total_size += pic->header_size;
710  av_log(avctx, AV_LOG_DEBUG, "Output buffer size %"SIZE_SPECIFIER"\n", total_size);
711 
712  hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&mapped_data);
713  if (FAILED(hr)) {
714  err = AVERROR_UNKNOWN;
715  goto end;
716  }
717 
718  err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
719  if (err < 0)
720  goto end;
721  ptr = pkt->data;
722 
723  memcpy(ptr, mapped_data, pic->header_size);
724 
725  ptr += pic->header_size;
726  mapped_data += pic->aligned_header_size;
727  total_size -= pic->header_size;
728 
729  memcpy(ptr, mapped_data, total_size);
730 
731  ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
732 
733 end:
735  pic->output_buffer = NULL;
736  return err;
737 }
738 
740  FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
741 {
743  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
744  D3D12VAEncodePicture *pic = base_pic->priv;
745  AVPacket *pkt_ptr = pkt;
746  int err = 0;
747 
748  err = d3d12va_encode_wait(avctx, base_pic);
749  if (err < 0)
750  return err;
751 
752  if (ctx->codec->get_coded_data)
753  err = ctx->codec->get_coded_data(avctx, pic, pkt);
754  else
755  err = d3d12va_encode_get_coded_data(avctx, pic, pkt);
756 
757  if (err < 0)
758  return err;
759 
760  av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
761  base_pic->display_order, base_pic->encode_order);
762 
764  pkt_ptr, 0);
765 
766  return 0;
767 }
768 
770 {
771  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
774  const AVPixFmtDescriptor *desc;
775  int i, depth;
776 
778  if (!desc) {
779  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
780  base_ctx->input_frames->sw_format);
781  return AVERROR(EINVAL);
782  }
783 
784  depth = desc->comp[0].depth;
785  for (i = 1; i < desc->nb_components; i++) {
786  if (desc->comp[i].depth != depth) {
787  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
788  desc->name);
789  return AVERROR(EINVAL);
790  }
791  }
792  av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
793  desc->name);
794 
795  av_assert0(ctx->codec->profiles);
796  for (i = 0; (ctx->codec->profiles[i].av_profile !=
797  AV_PROFILE_UNKNOWN); i++) {
798  profile = &ctx->codec->profiles[i];
799  if (depth != profile->depth ||
800  desc->nb_components != profile->nb_components)
801  continue;
802  if (desc->nb_components > 1 &&
803  (desc->log2_chroma_w != profile->log2_chroma_w ||
804  desc->log2_chroma_h != profile->log2_chroma_h))
805  continue;
806  if (avctx->profile != profile->av_profile &&
807  avctx->profile != AV_PROFILE_UNKNOWN)
808  continue;
809 
810  ctx->profile = profile;
811  break;
812  }
813  if (!ctx->profile) {
814  av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
815  return AVERROR(ENOSYS);
816  }
817 
818  avctx->profile = profile->av_profile;
819  return 0;
820 }
821 
823  // Bitrate Quality
824  // | Maxrate | HRD/VBV
825  { 0 }, // | | | |
826  { RC_MODE_CQP, "CQP", 0, 0, 1, 0, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP },
827  { RC_MODE_CBR, "CBR", 1, 0, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR },
828  { RC_MODE_VBR, "VBR", 1, 1, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR },
829  { RC_MODE_QVBR, "QVBR", 1, 1, 1, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR },
830 };
831 
833 {
834  HRESULT hr;
836  D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE d3d12_rc_mode = {
837  .Codec = ctx->codec->d3d12_codec,
838  };
839 
840  if (!rc_mode->d3d12_mode)
841  return 0;
842 
843  d3d12_rc_mode.IsSupported = 0;
844  d3d12_rc_mode.RateControlMode = rc_mode->d3d12_mode;
845 
846  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
847  D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE,
848  &d3d12_rc_mode, sizeof(d3d12_rc_mode));
849  if (FAILED(hr)) {
850  av_log(avctx, AV_LOG_ERROR, "Failed to check rate control support.\n");
851  return 0;
852  }
853 
854  return d3d12_rc_mode.IsSupported;
855 }
856 
858 {
860  int64_t rc_target_bitrate;
861  int64_t rc_peak_bitrate;
862  int rc_quality;
863  int64_t hrd_buffer_size;
864  int64_t hrd_initial_buffer_fullness;
865  int fr_num, fr_den;
867 
868 #define SET_QP_RANGE(ctl) do { \
869  if (avctx->qmin > 0 || avctx->qmax > 0) { \
870  ctl->MinQP = avctx->qmin; \
871  ctl->MaxQP = avctx->qmax; \
872  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_QP_RANGE; \
873  } \
874  } while(0)
875 
876 #define SET_MAX_FRAME_SIZE(ctl) do { \
877  if (ctx->max_frame_size > 0) { \
878  ctl->MaxFrameBitSize = ctx->max_frame_size * 8; \
879  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_MAX_FRAME_SIZE; \
880  } \
881  } while(0)
882 
883  // Rate control mode selection:
884  // * If the user has set a mode explicitly with the rc_mode option,
885  // use it and fail if it is not available.
886  // * If an explicit QP option has been set, use CQP.
887  // * If the codec is CQ-only, use CQP.
888  // * If the QSCALE avcodec option is set, use CQP.
889  // * If bitrate and quality are both set, try QVBR.
890  // * If quality is set, try CQP.
891  // * If bitrate and maxrate are set and have the same value, try CBR.
892  // * If a bitrate is set, try VBR, then CBR.
893  // * If no bitrate is set, try CQP.
894 
895 #define TRY_RC_MODE(mode, fail) do { \
896  rc_mode = &d3d12va_encode_rc_modes[mode]; \
897  if (!(rc_mode->d3d12_mode && check_rate_control_support(avctx, rc_mode))) { \
898  if (fail) { \
899  av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
900  "RC mode.\n", rc_mode->name); \
901  return AVERROR(EINVAL); \
902  } \
903  av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
904  "RC mode.\n", rc_mode->name); \
905  rc_mode = NULL; \
906  } else { \
907  goto rc_mode_found; \
908  } \
909  } while (0)
910 
911  if (ctx->explicit_rc_mode)
912  TRY_RC_MODE(ctx->explicit_rc_mode, 1);
913 
914  if (ctx->explicit_qp)
916 
919 
920  if (avctx->flags & AV_CODEC_FLAG_QSCALE)
922 
923  if (avctx->bit_rate > 0 && avctx->global_quality > 0)
925 
926  if (avctx->global_quality > 0) {
928  }
929 
930  if (avctx->bit_rate > 0 && avctx->rc_max_rate == avctx->bit_rate)
932 
933  if (avctx->bit_rate > 0) {
936  } else {
938  }
939 
940  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
941  "RC mode compatible with selected options.\n");
942  return AVERROR(EINVAL);
943 
944 rc_mode_found:
945  if (rc_mode->bitrate) {
946  if (avctx->bit_rate <= 0) {
947  av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s "
948  "RC mode.\n", rc_mode->name);
949  return AVERROR(EINVAL);
950  }
951 
952  if (rc_mode->maxrate) {
953  if (avctx->rc_max_rate > 0) {
954  if (avctx->rc_max_rate < avctx->bit_rate) {
955  av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: "
956  "bitrate (%"PRId64") must not be greater than "
957  "maxrate (%"PRId64").\n", avctx->bit_rate,
958  avctx->rc_max_rate);
959  return AVERROR(EINVAL);
960  }
961  rc_target_bitrate = avctx->bit_rate;
962  rc_peak_bitrate = avctx->rc_max_rate;
963  } else {
964  // We only have a target bitrate, but this mode requires
965  // that a maximum rate be supplied as well. Since the
966  // user does not want this to be a constraint, arbitrarily
967  // pick a maximum rate of double the target rate.
968  rc_target_bitrate = avctx->bit_rate;
969  rc_peak_bitrate = 2 * avctx->bit_rate;
970  }
971  } else {
972  if (avctx->rc_max_rate > avctx->bit_rate) {
973  av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored "
974  "in %s RC mode.\n", rc_mode->name);
975  }
976  rc_target_bitrate = avctx->bit_rate;
977  rc_peak_bitrate = 0;
978  }
979  } else {
980  rc_target_bitrate = 0;
981  rc_peak_bitrate = 0;
982  }
983 
984  if (rc_mode->quality) {
985  if (ctx->explicit_qp) {
986  rc_quality = ctx->explicit_qp;
987  } else if (avctx->global_quality > 0) {
988  if (avctx->flags & AV_CODEC_FLAG_QSCALE)
989  rc_quality = avctx->global_quality / FF_QP2LAMBDA;
990  else
991  rc_quality = avctx->global_quality;
992  } else {
993  rc_quality = ctx->codec->default_quality;
994  av_log(avctx, AV_LOG_WARNING, "No quality level set; "
995  "using default (%d).\n", rc_quality);
996  }
997  } else {
998  rc_quality = 0;
999  }
1000 
1001  if (rc_mode->hrd) {
1002  if (avctx->rc_buffer_size)
1003  hrd_buffer_size = avctx->rc_buffer_size;
1004  else if (avctx->rc_max_rate > 0)
1005  hrd_buffer_size = avctx->rc_max_rate;
1006  else
1007  hrd_buffer_size = avctx->bit_rate;
1008  if (avctx->rc_initial_buffer_occupancy) {
1009  if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1010  av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1011  "must have initial buffer size (%d) <= "
1012  "buffer size (%"PRId64").\n",
1013  avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1014  return AVERROR(EINVAL);
1015  }
1016  hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1017  } else {
1018  hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1019  }
1020  } else {
1021  if (avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
1022  av_log(avctx, AV_LOG_WARNING, "Buffering settings are ignored "
1023  "in %s RC mode.\n", rc_mode->name);
1024  }
1025 
1026  hrd_buffer_size = 0;
1027  hrd_initial_buffer_fullness = 0;
1028  }
1029 
1030  if (rc_target_bitrate > UINT32_MAX ||
1031  hrd_buffer_size > UINT32_MAX ||
1032  hrd_initial_buffer_fullness > UINT32_MAX) {
1033  av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1034  "greater are not supported by D3D12.\n");
1035  return AVERROR(EINVAL);
1036  }
1037 
1038  ctx->rc_quality = rc_quality;
1039 
1040  av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s.\n", rc_mode->name);
1041 
1042  if (rc_mode->quality)
1043  av_log(avctx, AV_LOG_VERBOSE, "RC quality: %d.\n", rc_quality);
1044 
1045  if (rc_mode->hrd) {
1046  av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1047  "initial fullness %"PRId64" bits.\n",
1048  hrd_buffer_size, hrd_initial_buffer_fullness);
1049  }
1050 
1051  if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1052  av_reduce(&fr_num, &fr_den,
1053  avctx->framerate.num, avctx->framerate.den, 65535);
1054  else
1055  av_reduce(&fr_num, &fr_den,
1056  avctx->time_base.den, avctx->time_base.num, 65535);
1057 
1058  av_log(avctx, AV_LOG_VERBOSE, "RC framerate: %d/%d (%.2f fps).\n",
1059  fr_num, fr_den, (double)fr_num / fr_den);
1060 
1061  ctx->rc.Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
1062  ctx->rc.TargetFrameRate.Numerator = fr_num;
1063  ctx->rc.TargetFrameRate.Denominator = fr_den;
1064  ctx->rc.Mode = rc_mode->d3d12_mode;
1065 
1066  switch (rc_mode->mode) {
1067  case RC_MODE_CQP:
1068  // cqp ConfigParams will be updated in ctx->codec->configure.
1069  break;
1070  case RC_MODE_CBR: {
1071  D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR *cbr_ctl;
1072 
1073  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR);
1074  cbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1075  if (!cbr_ctl)
1076  return AVERROR(ENOMEM);
1077 
1078  cbr_ctl->TargetBitRate = rc_target_bitrate;
1079  cbr_ctl->VBVCapacity = hrd_buffer_size;
1080  cbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1081  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1082 
1083  SET_QP_RANGE(cbr_ctl);
1084  SET_MAX_FRAME_SIZE(cbr_ctl);
1085 
1086  ctx->rc.ConfigParams.pConfiguration_CBR = cbr_ctl;
1087  break;
1088  }
1089  case RC_MODE_VBR: {
1090  D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR *vbr_ctl;
1091 
1092  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR);
1093  vbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1094  if (!vbr_ctl)
1095  return AVERROR(ENOMEM);
1096 
1097  vbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1098  vbr_ctl->PeakBitRate = rc_peak_bitrate;
1099  vbr_ctl->VBVCapacity = hrd_buffer_size;
1100  vbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1101  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1102 
1103  SET_QP_RANGE(vbr_ctl);
1104  SET_MAX_FRAME_SIZE(vbr_ctl);
1105 
1106  ctx->rc.ConfigParams.pConfiguration_VBR = vbr_ctl;
1107  break;
1108  }
1109  case RC_MODE_QVBR: {
1110  D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR *qvbr_ctl;
1111 
1112  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR);
1113  qvbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1114  if (!qvbr_ctl)
1115  return AVERROR(ENOMEM);
1116 
1117  qvbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1118  qvbr_ctl->PeakBitRate = rc_peak_bitrate;
1119  qvbr_ctl->ConstantQualityTarget = rc_quality;
1120 
1121  SET_QP_RANGE(qvbr_ctl);
1122  SET_MAX_FRAME_SIZE(qvbr_ctl);
1123 
1124  ctx->rc.ConfigParams.pConfiguration_QVBR = qvbr_ctl;
1125  break;
1126  }
1127  default:
1128  break;
1129  }
1130  return 0;
1131 }
1132 
1134 {
1135  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1137  uint32_t ref_l0, ref_l1;
1138  int err;
1139  HRESULT hr;
1140  D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT support;
1141  union {
1142  D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
1143  D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
1144 #if CONFIG_AV1_D3D12VA_ENCODER
1145  D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
1146 #endif
1147  } codec_support;
1148 
1149  support.NodeIndex = 0;
1150  support.Codec = ctx->codec->d3d12_codec;
1151  support.Profile = ctx->profile->d3d12_profile;
1152 
1153  switch (ctx->codec->d3d12_codec) {
1154  case D3D12_VIDEO_ENCODER_CODEC_H264:
1155  support.PictureSupport.DataSize = sizeof(codec_support.h264);
1156  support.PictureSupport.pH264Support = &codec_support.h264;
1157  break;
1158 
1159  case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1160  support.PictureSupport.DataSize = sizeof(codec_support.hevc);
1161  support.PictureSupport.pHEVCSupport = &codec_support.hevc;
1162  break;
1163 
1164 #if CONFIG_AV1_D3D12VA_ENCODER
1165  case D3D12_VIDEO_ENCODER_CODEC_AV1:
1166  memset(&codec_support.av1, 0, sizeof(codec_support.av1));
1167  support.PictureSupport.DataSize = sizeof(codec_support.av1);
1168  support.PictureSupport.pAV1Support = &codec_support.av1;
1169  break;
1170 #endif
1171  default:
1172  av_assert0(0);
1173  }
1174 
1175  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1176  &support, sizeof(support));
1177  if (FAILED(hr))
1178  return AVERROR(EINVAL);
1179 
1180  if (support.IsSupported) {
1181  switch (ctx->codec->d3d12_codec) {
1182  case D3D12_VIDEO_ENCODER_CODEC_H264:
1183  ref_l0 = FFMIN(support.PictureSupport.pH264Support->MaxL0ReferencesForP,
1184  support.PictureSupport.pH264Support->MaxL1ReferencesForB ?
1185  support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX);
1186  ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB;
1187  break;
1188 
1189  case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1190  ref_l0 = FFMIN(support.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
1191  support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB ?
1192  support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX);
1193  ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
1194  break;
1195 
1196 #if CONFIG_AV1_D3D12VA_ENCODER
1197  case D3D12_VIDEO_ENCODER_CODEC_AV1:
1198  ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
1199  // AV1 doesn't use traditional L1 references like H.264/HEVC
1200  ref_l1 = 0;
1201  break;
1202 #endif
1203  default:
1204  av_assert0(0);
1205  }
1206  } else {
1207  ref_l0 = ref_l1 = 0;
1208  }
1209 
1210  if (ref_l0 > 0 && ref_l1 > 0 && ctx->bi_not_empty) {
1211  base_ctx->p_to_gpb = 1;
1212  av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, "
1213  "replacing them with B-frames.\n");
1214  }
1215 
1216  err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1, ctx->codec->flags, 0);
1217  if (err < 0)
1218  return err;
1219 
1220  return 0;
1221 }
1222 
1224 {
1225  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1227  AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
1228  HRESULT hr;
1229 
1230  D3D12_VIDEO_ENCODER_DESC desc = {
1231  .NodeMask = 0,
1232  .Flags = D3D12_VIDEO_ENCODER_FLAG_NONE,
1233  .EncodeCodec = ctx->codec->d3d12_codec,
1234  .EncodeProfile = ctx->profile->d3d12_profile,
1235  .InputFormat = frames_hwctx->format,
1236  .CodecConfiguration = ctx->codec_conf,
1237  .MaxMotionEstimationPrecision = D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM,
1238  };
1239 
1240  hr = ID3D12VideoDevice3_CreateVideoEncoder(ctx->video_device3, &desc, &IID_ID3D12VideoEncoder,
1241  (void **)&ctx->encoder);
1242  if (FAILED(hr)) {
1243  av_log(avctx, AV_LOG_ERROR, "Failed to create encoder.\n");
1244  return AVERROR(EINVAL);
1245  }
1246 
1247  return 0;
1248 }
1249 
1251 {
1253  HRESULT hr;
1254 
1255  D3D12_VIDEO_ENCODER_HEAP_DESC desc = {
1256  .NodeMask = 0,
1257  .Flags = D3D12_VIDEO_ENCODER_HEAP_FLAG_NONE,
1258  .EncodeCodec = ctx->codec->d3d12_codec,
1259  .EncodeProfile = ctx->profile->d3d12_profile,
1260  .EncodeLevel = ctx->level,
1261  .ResolutionsListCount = 1,
1262  .pResolutionList = &ctx->resolution,
1263  };
1264 
1265  hr = ID3D12VideoDevice3_CreateVideoEncoderHeap(ctx->video_device3, &desc,
1266  &IID_ID3D12VideoEncoderHeap, (void **)&ctx->encoder_heap);
1267  if (FAILED(hr)) {
1268  av_log(avctx, AV_LOG_ERROR, "Failed to create encoder heap.\n");
1269  return AVERROR(EINVAL);
1270  }
1271 
1272  return 0;
1273 }
1274 
1275 static void d3d12va_encode_free_buffer(void *opaque, uint8_t *data)
1276 {
1277  ID3D12Resource *pResource;
1278 
1279  pResource = (ID3D12Resource *)data;
1280  D3D12_OBJECT_RELEASE(pResource);
1281 }
1282 
1284 {
1285  AVCodecContext *avctx = opaque;
1286  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1288  ID3D12Resource *pResource = NULL;
1289  HRESULT hr;
1290  AVBufferRef *ref;
1291  D3D12_HEAP_PROPERTIES heap_props;
1292  D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_READBACK;
1293 
1294  D3D12_RESOURCE_DESC desc = {
1295  .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1296  .Alignment = 0,
1297  .Width = FFALIGN(3 * base_ctx->surface_width * base_ctx->surface_height + (1 << 16),
1298  D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT),
1299  .Height = 1,
1300  .DepthOrArraySize = 1,
1301  .MipLevels = 1,
1302  .Format = DXGI_FORMAT_UNKNOWN,
1303  .SampleDesc = { .Count = 1, .Quality = 0 },
1304  .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1305  .Flags = D3D12_RESOURCE_FLAG_NONE,
1306  };
1307 
1308  ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(ctx->hwctx->device, &heap_props, 0, heap_type);
1309 
1310  hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
1311  &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource,
1312  (void **)&pResource);
1313 
1314  if (FAILED(hr)) {
1315  av_log(avctx, AV_LOG_ERROR, "Failed to create d3d12 buffer.\n");
1316  return NULL;
1317  }
1318 
1319  ref = av_buffer_create((uint8_t *)(uintptr_t)pResource,
1320  sizeof(pResource),
1322  avctx, AV_BUFFER_FLAG_READONLY);
1323  if (!ref) {
1324  D3D12_OBJECT_RELEASE(pResource);
1325  return NULL;
1326  }
1327 
1328  return ref;
1329 }
1330 
1332 {
1333  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1335  AVD3D12VAFramesContext *frames_ctx = base_ctx->input_frames->hwctx;
1336  HRESULT hr;
1337 
1338  ctx->req.NodeIndex = 0;
1339  ctx->req.Codec = ctx->codec->d3d12_codec;
1340  ctx->req.Profile = ctx->profile->d3d12_profile;
1341  ctx->req.InputFormat = frames_ctx->format;
1342  ctx->req.PictureTargetResolution = ctx->resolution;
1343 
1344  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1345  D3D12_FEATURE_VIDEO_ENCODER_RESOURCE_REQUIREMENTS,
1346  &ctx->req, sizeof(ctx->req));
1347  if (FAILED(hr)) {
1348  av_log(avctx, AV_LOG_ERROR, "Failed to check encoder resource requirements support.\n");
1349  return AVERROR(EINVAL);
1350  }
1351 
1352  if (!ctx->req.IsSupported) {
1353  av_log(avctx, AV_LOG_ERROR, "Encoder resource requirements unsupported.\n");
1354  return AVERROR(EINVAL);
1355  }
1356 
1357  ctx->output_buffer_pool = av_buffer_pool_init2(sizeof(ID3D12Resource *), avctx,
1359  if (!ctx->output_buffer_pool)
1360  return AVERROR(ENOMEM);
1361 
1362  return 0;
1363 }
1364 
1366 {
1368  ID3D12CommandAllocator *command_allocator = NULL;
1369  int err = AVERROR_UNKNOWN;
1370  HRESULT hr;
1371 
1372  D3D12_COMMAND_QUEUE_DESC queue_desc = {
1373  .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
1374  .Priority = 0,
1375  .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
1376  .NodeMask = 0,
1377  };
1378 
1381  if (!ctx->allocator_queue)
1382  return AVERROR(ENOMEM);
1383 
1384  hr = ID3D12Device_CreateFence(ctx->hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
1385  &IID_ID3D12Fence, (void **)&ctx->sync_ctx.fence);
1386  if (FAILED(hr)) {
1387  av_log(avctx, AV_LOG_ERROR, "Failed to create fence(%lx)\n", (long)hr);
1388  err = AVERROR_UNKNOWN;
1389  goto fail;
1390  }
1391 
1392  ctx->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
1393  if (!ctx->sync_ctx.event)
1394  goto fail;
1395 
1396  err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
1397  if (err < 0)
1398  goto fail;
1399 
1400  hr = ID3D12Device_CreateCommandQueue(ctx->hwctx->device, &queue_desc,
1401  &IID_ID3D12CommandQueue, (void **)&ctx->command_queue);
1402  if (FAILED(hr)) {
1403  av_log(avctx, AV_LOG_ERROR, "Failed to create command queue(%lx)\n", (long)hr);
1404  err = AVERROR_UNKNOWN;
1405  goto fail;
1406  }
1407 
1408  hr = ID3D12Device_CreateCommandList(ctx->hwctx->device, 0, queue_desc.Type,
1409  command_allocator, NULL, &IID_ID3D12CommandList,
1410  (void **)&ctx->command_list);
1411  if (FAILED(hr)) {
1412  av_log(avctx, AV_LOG_ERROR, "Failed to create command list(%lx)\n", (long)hr);
1413  err = AVERROR_UNKNOWN;
1414  goto fail;
1415  }
1416 
1417  hr = ID3D12VideoEncodeCommandList2_Close(ctx->command_list);
1418  if (FAILED(hr)) {
1419  av_log(avctx, AV_LOG_ERROR, "Failed to close the command list(%lx)\n", (long)hr);
1420  err = AVERROR_UNKNOWN;
1421  goto fail;
1422  }
1423 
1424  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
1425 
1426  err = d3d12va_sync_with_gpu(avctx);
1427  if (err < 0)
1428  goto fail;
1429 
1430  err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
1431  if (err < 0)
1432  goto fail;
1433 
1434  return 0;
1435 
1436 fail:
1437  D3D12_OBJECT_RELEASE(command_allocator);
1438  return err;
1439 }
1440 
1442 {
1443  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1445  AVD3D12VAFramesContext *hwctx;
1446  enum AVPixelFormat recon_format;
1447  int err;
1448 
1449  err = ff_hw_base_get_recon_format(base_ctx, NULL, &recon_format);
1450  if (err < 0)
1451  return err;
1452 
1453  base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref);
1454  if (!base_ctx->recon_frames_ref)
1455  return AVERROR(ENOMEM);
1456 
1457  base_ctx->recon_frames = (AVHWFramesContext *)base_ctx->recon_frames_ref->data;
1458  hwctx = (AVD3D12VAFramesContext *)base_ctx->recon_frames->hwctx;
1459 
1460  base_ctx->recon_frames->format = AV_PIX_FMT_D3D12;
1461  base_ctx->recon_frames->sw_format = recon_format;
1462  base_ctx->recon_frames->width = base_ctx->surface_width;
1463  base_ctx->recon_frames->height = base_ctx->surface_height;
1464 
1465  hwctx->resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
1466  D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1467  if (ctx->is_texture_array) {
1468  base_ctx->recon_frames->initial_pool_size = MAX_DPB_SIZE + 1;
1470  }
1471 
1472  err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
1473  if (err < 0) {
1474  av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
1475  "frame context: %d.\n", err);
1476  return err;
1477  }
1478 
1479  return 0;
1480 }
1481 
1483  .priv_size = sizeof(D3D12VAEncodePicture),
1484 
1486 
1487  .issue = &d3d12va_encode_issue,
1488 
1490 
1491  .free = &d3d12va_encode_free,
1492 };
1493 
1495 {
1496  return ff_hw_base_encode_receive_packet(avctx->priv_data, avctx, pkt);
1497 }
1498 
1500 {
1501  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1503  D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
1504  D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
1505  int err;
1506  HRESULT hr;
1507 
1508  err = ff_hw_base_encode_init(avctx, base_ctx);
1509  if (err < 0)
1510  goto fail;
1511 
1512  base_ctx->op = &d3d12va_type;
1513 
1514  ctx->hwctx = base_ctx->device->hwctx;
1515 
1516  ctx->resolution.Width = base_ctx->input_frames->width;
1517  ctx->resolution.Height = base_ctx->input_frames->height;
1518 
1519  hr = ID3D12Device_QueryInterface(ctx->hwctx->device, &IID_ID3D12Device3, (void **)&ctx->device3);
1520  if (FAILED(hr)) {
1521  av_log(avctx, AV_LOG_ERROR, "ID3D12Device3 interface is not supported.\n");
1522  err = AVERROR_UNKNOWN;
1523  goto fail;
1524  }
1525 
1526  hr = ID3D12Device3_QueryInterface(ctx->device3, &IID_ID3D12VideoDevice3, (void **)&ctx->video_device3);
1527  if (FAILED(hr)) {
1528  av_log(avctx, AV_LOG_ERROR, "ID3D12VideoDevice3 interface is not supported.\n");
1529  err = AVERROR_UNKNOWN;
1530  goto fail;
1531  }
1532 
1533  if (FAILED(ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1534  &support, sizeof(support))) && !support.VideoEncodeSupport) {
1535  av_log(avctx, AV_LOG_ERROR, "D3D12 video device has no video encoder support.\n");
1536  err = AVERROR(EINVAL);
1537  goto fail;
1538  }
1539 
1540  format_info.Format = ((AVD3D12VAFramesContext *)base_ctx->input_frames->hwctx)->format;
1541  if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
1542  &format_info, sizeof(format_info)))) {
1543  av_log(avctx, AV_LOG_ERROR, "Failed to query format plane count: %#lx\n", hr);
1544  err = AVERROR_EXTERNAL;
1545  goto fail;
1546  }
1547  ctx->plane_count = format_info.PlaneCount;
1548 
1549  err = d3d12va_encode_set_profile(avctx);
1550  if (err < 0)
1551  goto fail;
1552 
1553  if (ctx->codec->set_tile) {
1554  err = ctx->codec->set_tile(avctx);
1555  if (err < 0)
1556  goto fail;
1557  }
1558 
1559  err = d3d12va_encode_init_rate_control(avctx);
1560  if (err < 0)
1561  goto fail;
1562 
1563  if (ctx->codec->get_encoder_caps) {
1564  err = ctx->codec->get_encoder_caps(avctx);
1565  if (err < 0)
1566  goto fail;
1567  }
1568 
1569  err = d3d12va_encode_init_gop_structure(avctx);
1570  if (err < 0)
1571  goto fail;
1572 
1573  if (!(ctx->codec->flags & FF_HW_FLAG_SLICE_CONTROL) && avctx->slices > 0) {
1574  av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested "
1575  "but this codec does not support controlling slices.\n");
1576  }
1577 
1579  if (err < 0)
1580  goto fail;
1581 
1583  if (err < 0)
1584  goto fail;
1585 
1586  if (ctx->codec->configure) {
1587  err = ctx->codec->configure(avctx);
1588  if (err < 0)
1589  goto fail;
1590  }
1591 
1592  if (ctx->codec->init_sequence_params) {
1593  err = ctx->codec->init_sequence_params(avctx);
1594  if (err < 0) {
1595  av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
1596  "failed: %d.\n", err);
1597  goto fail;
1598  }
1599  }
1600 
1601  if (ctx->codec->set_level) {
1602  err = ctx->codec->set_level(avctx);
1603  if (err < 0)
1604  goto fail;
1605  }
1606 
1608  if (err < 0)
1609  goto fail;
1610 
1611  base_ctx->output_delay = base_ctx->b_per_p;
1612  base_ctx->decode_delay = base_ctx->max_b_depth;
1613 
1614  err = d3d12va_create_encoder(avctx);
1615  if (err < 0)
1616  goto fail;
1617 
1618  err = d3d12va_create_encoder_heap(avctx);
1619  if (err < 0)
1620  goto fail;
1621 
1622  base_ctx->async_encode = 1;
1623  base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
1624  sizeof(D3D12VAEncodePicture *), 0);
1625  if (!base_ctx->encode_fifo)
1626  return AVERROR(ENOMEM);
1627 
1628  return 0;
1629 
1630 fail:
1631  return err;
1632 }
1633 
1635 {
1636  int num_allocator = 0;
1637  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1639  FFHWBaseEncodePicture *pic, *next;
1640  CommandAllocator allocator;
1641 
1642  if (!base_ctx->frame)
1643  return 0;
1644 
1645  for (pic = base_ctx->pic_start; pic; pic = next) {
1646  next = pic->next;
1647  d3d12va_encode_free(avctx, pic);
1648  }
1649 
1651 
1652  av_buffer_pool_uninit(&ctx->output_buffer_pool);
1653 
1654  D3D12_OBJECT_RELEASE(ctx->command_list);
1655  D3D12_OBJECT_RELEASE(ctx->command_queue);
1656 
1657  if (ctx->allocator_queue) {
1658  while (av_fifo_read(ctx->allocator_queue, &allocator, 1) >= 0) {
1659  num_allocator++;
1661  }
1662 
1663  av_log(avctx, AV_LOG_VERBOSE, "Total number of command allocators reused: %d\n", num_allocator);
1664  }
1665 
1666  av_fifo_freep2(&ctx->allocator_queue);
1667 
1668  D3D12_OBJECT_RELEASE(ctx->sync_ctx.fence);
1669  if (ctx->sync_ctx.event)
1670  CloseHandle(ctx->sync_ctx.event);
1671 
1672  D3D12_OBJECT_RELEASE(ctx->encoder_heap);
1673  D3D12_OBJECT_RELEASE(ctx->encoder);
1674  D3D12_OBJECT_RELEASE(ctx->video_device3);
1675  D3D12_OBJECT_RELEASE(ctx->device3);
1676 
1677  ff_hw_base_encode_close(base_ctx);
1678 
1679  return 0;
1680 }
FFHWBaseEncodeContext::output_delay
int64_t output_delay
Definition: hw_base_encode.h:169
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
AVD3D12VAFramesContext::flags
AVD3D12VAFrameFlags flags
A combination of AVD3D12VAFrameFlags.
Definition: hwcontext_d3d12va.h:206
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
FFHWBaseEncodeContext::recon_frames_ref
AVBufferRef * recon_frames_ref
Definition: hw_base_encode.h:156
FFHWBaseEncodePicture::next
struct FFHWBaseEncodePicture * next
Definition: hw_base_encode.h:67
d3d12va_encode_set_profile
static int d3d12va_encode_set_profile(AVCodecContext *avctx)
Definition: d3d12va_encode.c:769
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
FFHWBaseEncodePicture::priv
void * priv
Definition: hw_base_encode.h:63
FFHWBaseEncodePicture::codec_priv
void * codec_priv
Definition: hw_base_encode.h:65
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
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:200
AV_CODEC_FLAG_QSCALE
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition: avcodec.h:213
int64_t
long long int64_t
Definition: coverity.c:34
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:226
d3d12va_encode_create_recon_frames
static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1441
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
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
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
pixdesc.h
D3D12VAEncodePicture::input_surface
AVD3D12VAFrame * input_surface
Definition: d3d12va_encode.h:46
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:263
AVPacket::data
uint8_t * data
Definition: packet.h:588
ff_hw_base_encode_init
int ff_hw_base_encode_init(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx)
Definition: hw_base_encode.c:781
encode.h
d3d12va_encode.h
d3d12va_encode_get_coded_data
static int d3d12va_encode_get_coded_data(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AVPacket *pkt)
Definition: d3d12va_encode.c:697
data
const char data[16]
Definition: mxf.c:149
FFHWBaseEncodePicture::recon_image
AVFrame * recon_image
Definition: hw_base_encode.h:84
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:448
D3D12VAEncodePicture::resolved_metadata
ID3D12Resource * resolved_metadata
Definition: d3d12va_encode.h:53
FFHWBaseEncodeContext
Definition: hw_base_encode.h:122
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:551
d3d12va_encode_output
static int d3d12va_encode_output(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
Definition: d3d12va_encode.c:739
ff_d3d12va_encode_hw_configs
const AVCodecHWConfigInternal *const ff_d3d12va_encode_hw_configs[]
Definition: d3d12va_encode.c:37
D3D12VAEncodePicture::output_buffer_ref
AVBufferRef * output_buffer_ref
Definition: d3d12va_encode.h:49
d3d12va_encode_free
static int d3d12va_encode_free(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
Definition: d3d12va_encode.c:648
d3d12va_sync_with_gpu
static int d3d12va_sync_with_gpu(AVCodecContext *avctx)
Definition: d3d12va_encode.c:55
FFHWBaseEncodePicture::type
int type
Definition: hw_base_encode.h:78
ff_hw_base_encode_close
int ff_hw_base_encode_close(FFHWBaseEncodeContext *ctx)
Definition: hw_base_encode.c:814
FFHWBaseEncodePicture::is_reference
int is_reference
Definition: hw_base_encode.h:87
fail
#define fail()
Definition: checkasm.h:208
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
D3D12VAEncodePicture::output_buffer
ID3D12Resource * output_buffer
Definition: d3d12va_encode.h:50
CommandAllocator::command_allocator
ID3D12CommandAllocator * command_allocator
Definition: d3d12va_encode.c:67
D3D12VAEncodePicture::recon_surface
AVD3D12VAFrame * recon_surface
Definition: d3d12va_encode.h:47
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:488
FFHWBaseEncodePicture::input_image
AVFrame * input_image
Definition: hw_base_encode.h:83
CommandAllocator::fence_value
uint64_t fence_value
Definition: d3d12va_encode.c:68
ff_hw_base_init_gop_structure
int ff_hw_base_init_gop_structure(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only)
Definition: hw_base_encode.c:662
av_reduce
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:35
AVRational::num
int num
Numerator.
Definition: rational.h:59
FFHWBaseEncodeContext::device
AVHWDeviceContext * device
Definition: hw_base_encode.h:149
avassert.h
d3d12va_encode_rc_modes
static const D3D12VAEncodeRCMode d3d12va_encode_rc_modes[]
Definition: d3d12va_encode.c:822
check_rate_control_support
static int check_rate_control_support(AVCodecContext *avctx, const D3D12VAEncodeRCMode *rc_mode)
Definition: d3d12va_encode.c:832
ff_hw_base_get_recon_format
int ff_hw_base_get_recon_format(FFHWBaseEncodeContext *ctx, const void *hwconfig, enum AVPixelFormat *fmt)
Definition: hw_base_encode.c:723
d3d12va_encode_get_buffer_size
static int d3d12va_encode_get_buffer_size(AVCodecContext *avctx, D3D12VAEncodePicture *pic, size_t *size)
Definition: d3d12va_encode.c:662
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
AV_PROFILE_UNKNOWN
#define AV_PROFILE_UNKNOWN
Definition: defs.h:65
d3d12va_encode_wait
static int d3d12va_encode_wait(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
Definition: d3d12va_encode.c:110
av_fifo_read
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition: fifo.c:240
AVCodecContext::rc_initial_buffer_occupancy
int rc_initial_buffer_occupancy
Number of bits which should be loaded into the rc buffer before decoding starts.
Definition: avcodec.h:1298
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
d3d12va_encode_issue
static int d3d12va_encode_issue(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
Definition: d3d12va_encode.c:195
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:390
AVCodecContext::global_quality
int global_quality
Global quality for codecs which cannot change it per frame.
Definition: avcodec.h:1217
D3D12_OBJECT_RELEASE
#define D3D12_OBJECT_RELEASE(pInterface)
A release macro used by D3D12 objects highly frequently.
Definition: hwcontext_d3d12va_internal.h:51
D3D12VAEncodePicture::header_size
int header_size
Definition: d3d12va_encode.h:43
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1415
SET_QP_RANGE
#define SET_QP_RANGE(ctl)
FFHWBaseEncodeContext::max_b_depth
int max_b_depth
Definition: hw_base_encode.h:188
FFHWBaseEncodeContext::async_encode
int async_encode
Definition: hw_base_encode.h:216
AVD3D12VAFrame::sync_ctx
AVD3D12VASyncContext sync_ctx
The sync context for the texture.
Definition: hwcontext_d3d12va.h:159
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
d3d12va_create_encoder_heap
static int d3d12va_create_encoder_heap(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1250
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ctx
AVFormatContext * ctx
Definition: movenc.c:49
D3D12VAEncodePicture::pic_ctl
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl
Definition: d3d12va_encode.h:57
AVD3D12VASyncContext
This struct is used to sync d3d12 execution.
Definition: hwcontext_d3d12va.h:104
d3d12va_encode_discard
static int d3d12va_encode_discard(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
Definition: d3d12va_encode.c:584
AVCodecContext::rc_max_rate
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:1270
AVD3D12VASyncContext::fence
ID3D12Fence * fence
D3D12 fence object.
Definition: hwcontext_d3d12va.h:108
D3D12VAEncodeRCMode
Definition: d3d12va_encode.h:104
FFHWBaseEncodeContext::pic_start
FFHWBaseEncodePicture * pic_start
Definition: hw_base_encode.h:160
FFHWBaseEncodeContext::b_per_p
int b_per_p
Definition: hw_base_encode.h:189
AVCodecContext::rc_buffer_size
int rc_buffer_size
decoder bitstream buffer size
Definition: avcodec.h:1255
d3d12va_discard_command_allocator
static int d3d12va_discard_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator, uint64_t fence_value)
Definition: d3d12va_encode.c:96
D3D12VAEncodePicture::fence_value
int fence_value
Definition: d3d12va_encode.h:59
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:213
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:481
D3D12VAEncodePicture::subresource_index
int subresource_index
Definition: d3d12va_encode.h:55
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
FFHWEncodePictureOperation
Definition: hw_base_encode.h:109
AVD3D12VAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_d3d12va.h:172
FF_HW_FLAG_CONSTANT_QUALITY_ONLY
@ FF_HW_FLAG_CONSTANT_QUALITY_ONLY
Definition: hw_base_encode.h:49
AV_PIX_FMT_D3D12
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition: pixfmt.h:440
AVD3D12VAFrame::texture
ID3D12Resource * texture
The texture in which the frame is located.
Definition: hwcontext_d3d12va.h:144
hwcontext_d3d12va.h
AVD3D12VAFramesContext::resource_flags
D3D12_RESOURCE_FLAGS resource_flags
Options for working with resources.
Definition: hwcontext_d3d12va.h:185
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
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avcodec.h:535
ff_hw_base_encode_set_output_property
int ff_hw_base_encode_set_output_property(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, FFHWBaseEncodePicture *pic, AVPacket *pkt, int flag_no_delay)
Definition: hw_base_encode.c:519
d3d12va_encode_free_buffer
static void d3d12va_encode_free_buffer(void *opaque, uint8_t *data)
Definition: d3d12va_encode.c:1275
FFHWEncodePictureOperation::priv_size
size_t priv_size
Definition: hw_base_encode.h:111
d3d12va_encode_create_metadata_buffers
static int d3d12va_encode_create_metadata_buffers(AVCodecContext *avctx, D3D12VAEncodePicture *pic)
Definition: d3d12va_encode.c:143
FFHWBaseEncodeContext::frame
AVFrame * frame
Definition: hw_base_encode.h:211
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:550
d3d12va_get_valid_command_allocator
static int d3d12va_get_valid_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator)
Definition: d3d12va_encode.c:71
d3d12va_encode_create_command_objects
static int d3d12va_encode_create_command_objects(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1365
ff_d3d12va_encode_init
int ff_d3d12va_encode_init(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1499
FFHWBaseEncodePicture::nb_refs
int nb_refs[MAX_REFERENCE_LIST_NUM]
Definition: hw_base_encode.h:97
CommandAllocator
Definition: d3d12va_encode.c:66
d3d12va_type
static const FFHWEncodePictureOperation d3d12va_type
Definition: d3d12va_encode.c:1482
MAX_DPB_SIZE
#define MAX_DPB_SIZE
Definition: hw_base_encode.h:26
D3D12VAEncodeProfile
Definition: d3d12va_encode.h:62
FFHWBaseEncodeContext::decode_delay
int64_t decode_delay
Definition: hw_base_encode.h:173
size
int size
Definition: twinvq_data.h:10344
ff_hw_base_encode_receive_packet
int ff_hw_base_encode_receive_packet(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, AVPacket *pkt)
Definition: hw_base_encode.c:558
SET_MAX_FRAME_SIZE
#define SET_MAX_FRAME_SIZE(ctl)
AVCodecHWConfigInternal
Definition: hwconfig.h:25
FFHWBaseEncodeContext::p_to_gpb
int p_to_gpb
Definition: hw_base_encode.h:194
FF_HW_FLAG_SLICE_CONTROL
@ FF_HW_FLAG_SLICE_CONTROL
Definition: hw_base_encode.h:47
FFHWBaseEncodePicture::encode_order
int64_t encode_order
Definition: hw_base_encode.h:70
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVD3D12VAFrame
D3D12VA frame descriptor for pool allocation.
Definition: hwcontext_d3d12va.h:138
RC_MODE_QVBR
@ RC_MODE_QVBR
Definition: d3d12va_encode.h:99
D3D12VA_VIDEO_ENC_ASYNC_DEPTH
#define D3D12VA_VIDEO_ENC_ASYNC_DEPTH
Definition: d3d12va_encode.h:40
D3D12VAEncodePicture::encoded_metadata
ID3D12Resource * encoded_metadata
Definition: d3d12va_encode.h:52
D3D12VAEncodePicture
Definition: d3d12va_encode.h:42
d3d12va_encode_alloc_output_buffer
static AVBufferRef * d3d12va_encode_alloc_output_buffer(void *opaque, size_t size)
Definition: d3d12va_encode.c:1283
HW_CONFIG_ENCODER_FRAMES
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition: hwconfig.h:98
d3d12va_encode_init
static int d3d12va_encode_init(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
Definition: d3d12va_encode.c:631
log.h
FFHWBaseEncodeContext::op
const struct FFHWEncodePictureOperation * op
Definition: hw_base_encode.h:127
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY
@ AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY
Indicates that frame data should be allocated using a texture array resource.
Definition: hwcontext_d3d12va.h:131
MAX_PARAM_BUFFER_SIZE
@ MAX_PARAM_BUFFER_SIZE
Definition: vaapi_encode.h:47
internal.h
TRY_RC_MODE
#define TRY_RC_MODE(mode, fail)
RC_MODE_VBR
@ RC_MODE_VBR
Definition: d3d12va_encode.h:98
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FFHWBaseEncodePicture::refs
struct FFHWBaseEncodePicture * refs[MAX_REFERENCE_LIST_NUM][MAX_PICTURE_REFERENCES]
Definition: hw_base_encode.h:98
d3d12va_fence_completion
static int d3d12va_fence_completion(AVD3D12VASyncContext *psync_ctx)
Definition: d3d12va_encode.c:42
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
profile
int profile
Definition: mxfenc.c:2297
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
d3d12va_create_encoder
static int d3d12va_create_encoder(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1223
avcodec.h
AVD3D12VAFramesContext::format
DXGI_FORMAT format
DXGI_FORMAT format.
Definition: hwcontext_d3d12va.h:177
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
d3d12va_encode_init_rate_control
static int d3d12va_encode_init_rate_control(AVCodecContext *avctx)
Definition: d3d12va_encode.c:857
FFHWBaseEncodePicture
Definition: hw_base_encode.h:61
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:265
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:153
D3D12VAEncodeContext
Definition: d3d12va_encode.h:146
FFHWBaseEncodeContext::device_ref
AVBufferRef * device_ref
Definition: hw_base_encode.h:148
FFHWBaseEncodeContext::encode_fifo
AVFifo * encode_fifo
Definition: hw_base_encode.h:219
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
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:119
ff_hw_base_encode_get_pictype_name
static const char * ff_hw_base_encode_get_pictype_name(const int type)
Definition: hw_base_encode.h:32
d3d12va_encode_prepare_output_buffers
static int d3d12va_encode_prepare_output_buffers(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1331
FFHWBaseEncodeContext::surface_height
int surface_height
Definition: hw_base_encode.h:141
FFHWBaseEncodeContext::async_depth
int async_depth
Definition: hw_base_encode.h:221
AVCodecContext
main external API structure.
Definition: avcodec.h:431
AVD3D12VASyncContext::event
HANDLE event
A handle to the event object that's raised when the fence reaches a certain value.
Definition: hwcontext_d3d12va.h:114
ff_get_encode_buffer
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition: encode.c:105
AVRational::den
int den
Denominator.
Definition: rational.h:60
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1618
d3d12va_encode_free_rc_params
static int d3d12va_encode_free_rc_params(AVCodecContext *avctx)
Definition: d3d12va_encode.c:606
D3D12VAEncodePicture::aligned_header_size
int aligned_header_size
Definition: d3d12va_encode.h:44
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
FFHWBaseEncodeContext::input_frames
AVHWFramesContext * input_frames
Definition: hw_base_encode.h:153
FFHWBaseEncodeContext::surface_width
int surface_width
Definition: hw_base_encode.h:140
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:190
desc
const char * desc
Definition: libsvtav1.c:78
FF_HW_PICTURE_TYPE_IDR
@ FF_HW_PICTURE_TYPE_IDR
Definition: hw_base_encode.h:39
FFHWBaseEncodePicture::encode_complete
int encode_complete
Definition: hw_base_encode.h:81
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
ff_d3d12va_encode_close
int ff_d3d12va_encode_close(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1634
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::slices
int slices
Number of slices.
Definition: avcodec.h:1021
ff_d3d12va_encode_receive_packet
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
Definition: d3d12va_encode.c:1494
AVPacket
This structure stores compressed data.
Definition: packet.h:565
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
d3d12va_encode_init_gop_structure
static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1133
FFHWBaseEncodeContext::recon_frames
AVHWFramesContext * recon_frames
Definition: hw_base_encode.h:157
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
AVD3D12VASyncContext::fence_value
uint64_t fence_value
The fence value used for sync.
Definition: hwcontext_d3d12va.h:119
FFHWBaseEncodePicture::encode_issued
int encode_issued
Definition: hw_base_encode.h:80
width
#define width
Definition: dsp.h:89
FF_QP2LAMBDA
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition: avutil.h:226
rc_mode
mfxU16 rc_mode
Definition: qsvenc.c:141
hwcontext_d3d12va_internal.h
FFHWBaseEncodePicture::display_order
int64_t display_order
Definition: hw_base_encode.h:69
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
AVD3D12VAFrame::subresource_index
int subresource_index
Index of the subresource within the texture.
Definition: hwcontext_d3d12va.h:152
RC_MODE_CQP
@ RC_MODE_CQP
Definition: d3d12va_encode.h:96
TRANSITION_BARRIER
#define TRANSITION_BARRIER(res, subres, before, after)
RC_MODE_CBR
@ RC_MODE_CBR
Definition: d3d12va_encode.h:97