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_SEQUENCE_CONTROL_FLAGS seq_flags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE;
215 
216  // Request intra refresh if enabled
217  if (ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
218  seq_flags |= D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_REQUEST_INTRA_REFRESH;
219  }
220 
221  D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
222  .SequenceControlDesc = {
223  .Flags = seq_flags,
224  .IntraRefreshConfig = ctx->intra_refresh,
225  .RateControl = ctx->rc,
226  .PictureTargetResolution = ctx->resolution,
227  .SelectedLayoutMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
228  .FrameSubregionsLayoutData = ctx->subregions_layout,
229  .CodecGopSequence = ctx->gop,
230  },
231  .pInputFrame = pic->input_surface->texture,
232  .InputFrameSubresource = 0,
233  };
234 
235  D3D12_VIDEO_ENCODER_ENCODEFRAME_OUTPUT_ARGUMENTS output_args = { 0 };
236 
237  D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS input_metadata = {
238  .EncoderCodec = ctx->codec->d3d12_codec,
239  .EncoderProfile = ctx->profile->d3d12_profile,
240  .EncoderInputFormat = frames_hwctx->format,
241  .EncodedPictureEffectiveResolution = ctx->resolution,
242  };
243 
244  D3D12_VIDEO_ENCODER_RESOLVE_METADATA_OUTPUT_ARGUMENTS output_metadata = { 0 };
245 
246  memset(data, 0, sizeof(data));
247 
248  av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
249  "as type %s.\n", base_pic->display_order, base_pic->encode_order,
251  if (base_pic->nb_refs[0] == 0 && base_pic->nb_refs[1] == 0) {
252  av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
253  } else {
254  av_log(avctx, AV_LOG_DEBUG, "L0 refers to");
255  for (i = 0; i < base_pic->nb_refs[0]; i++) {
256  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
257  base_pic->refs[0][i]->display_order, base_pic->refs[0][i]->encode_order);
258  }
259  av_log(avctx, AV_LOG_DEBUG, ".\n");
260 
261  if (base_pic->nb_refs[1]) {
262  av_log(avctx, AV_LOG_DEBUG, "L1 refers to");
263  for (i = 0; i < base_pic->nb_refs[1]; i++) {
264  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
265  base_pic->refs[1][i]->display_order, base_pic->refs[1][i]->encode_order);
266  }
267  av_log(avctx, AV_LOG_DEBUG, ".\n");
268  }
269  }
270 
271  av_assert0(!base_pic->encode_issued);
272  for (i = 0; i < base_pic->nb_refs[0]; i++) {
273  av_assert0(base_pic->refs[0][i]);
274  av_assert0(base_pic->refs[0][i]->encode_issued);
275  }
276  for (i = 0; i < base_pic->nb_refs[1]; i++) {
277  av_assert0(base_pic->refs[1][i]);
278  av_assert0(base_pic->refs[1][i]->encode_issued);
279  }
280 
281  av_log(avctx, AV_LOG_DEBUG, "Input surface is %p.\n", pic->input_surface->texture);
282 
283  pic->recon_surface = (AVD3D12VAFrame *)base_pic->recon_image->data[0];
284  av_log(avctx, AV_LOG_DEBUG, "Recon surface is %p.\n",
285  pic->recon_surface->texture);
286 
287  pic->subresource_index = ctx->is_texture_array ? pic->recon_surface->subresource_index : 0;
288 
289  pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
290  if (!pic->output_buffer_ref) {
291  err = AVERROR(ENOMEM);
292  goto fail;
293  }
294  pic->output_buffer = (ID3D12Resource *)pic->output_buffer_ref->data;
295  av_log(avctx, AV_LOG_DEBUG, "Output buffer is %p.\n",
296  pic->output_buffer);
297 
298  err = d3d12va_encode_create_metadata_buffers(avctx, pic);
299  if (err < 0)
300  goto fail;
301 
302  if (ctx->codec->init_picture_params) {
303  err = ctx->codec->init_picture_params(avctx, base_pic);
304  if (err < 0) {
305  av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
306  "parameters: %d.\n", err);
307  goto fail;
308  }
309  }
310 
311  if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
312  if (ctx->codec->write_sequence_header) {
313  bit_len = 8 * sizeof(data);
314  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
315  if (err < 0) {
316  av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
317  "header: %d.\n", err);
318  goto fail;
319  }
320  pic->header_size = (int)bit_len / 8;
321  pic->aligned_header_size = pic->header_size % ctx->req.CompressedBitstreamBufferAccessAlignment ?
322  FFALIGN(pic->header_size, ctx->req.CompressedBitstreamBufferAccessAlignment) :
323  pic->header_size;
324 
325  hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&ptr);
326  if (FAILED(hr)) {
327  err = AVERROR_UNKNOWN;
328  goto fail;
329  }
330 
331  memcpy(ptr, data, pic->aligned_header_size);
332  ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
333  }
334  }
335 
336  d3d12_refs.NumTexture2Ds = base_pic->nb_refs[0] + base_pic->nb_refs[1];
337  if (d3d12_refs.NumTexture2Ds) {
338  d3d12_refs.ppTexture2Ds = av_calloc(d3d12_refs.NumTexture2Ds,
339  sizeof(*d3d12_refs.ppTexture2Ds));
340  if (!d3d12_refs.ppTexture2Ds) {
341  err = AVERROR(ENOMEM);
342  goto fail;
343  }
344 
345  if (ctx->is_texture_array) {
346  d3d12_refs.pSubresources = av_calloc(d3d12_refs.NumTexture2Ds,
347  sizeof(*d3d12_refs.pSubresources));
348  if (!d3d12_refs.pSubresources) {
349  err = AVERROR(ENOMEM);
350  goto fail;
351  }
352  }
353 
354  i = 0;
355  for (j = 0; j < base_pic->nb_refs[0]; j++) {
356  d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->recon_surface->texture;
357  if (ctx->is_texture_array)
358  d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->subresource_index;
359  i++;
360  }
361  for (j = 0; j < base_pic->nb_refs[1]; j++) {
362  d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->recon_surface->texture;
363  if (ctx->is_texture_array)
364  d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->subresource_index;
365  i++;
366  }
367  }
368 
369  input_args.PictureControlDesc.IntraRefreshFrameIndex = ctx->intra_refresh_frame_index;
370  if (base_pic->is_reference)
371  input_args.PictureControlDesc.Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE;
372 
373  input_args.PictureControlDesc.PictureControlCodecData = pic->pic_ctl;
374  input_args.PictureControlDesc.ReferenceFrames = d3d12_refs;
375  input_args.CurrentFrameBitstreamMetadataSize = pic->aligned_header_size;
376 
377  output_args.Bitstream.pBuffer = pic->output_buffer;
378  output_args.Bitstream.FrameStartOffset = pic->aligned_header_size;
379  output_args.ReconstructedPicture.pReconstructedPicture = pic->recon_surface->texture;
380  output_args.ReconstructedPicture.ReconstructedPictureSubresource = ctx->is_texture_array ? pic->subresource_index : 0;
381  output_args.EncoderOutputMetadata.pBuffer = pic->encoded_metadata;
382  output_args.EncoderOutputMetadata.Offset = 0;
383 
384  input_metadata.HWLayoutMetadata.pBuffer = pic->encoded_metadata;
385  input_metadata.HWLayoutMetadata.Offset = 0;
386 
387  output_metadata.ResolvedLayoutMetadata.pBuffer = pic->resolved_metadata;
388  output_metadata.ResolvedLayoutMetadata.Offset = 0;
389 
390  err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
391  if (err < 0)
392  goto fail;
393 
394  hr = ID3D12CommandAllocator_Reset(command_allocator);
395  if (FAILED(hr)) {
396  err = AVERROR_UNKNOWN;
397  goto fail;
398  }
399 
400  hr = ID3D12VideoEncodeCommandList2_Reset(cmd_list, command_allocator);
401  if (FAILED(hr)) {
402  err = AVERROR_UNKNOWN;
403  goto fail;
404  }
405 
406 #define TRANSITION_BARRIER(res, subres, before, after) \
407  (D3D12_RESOURCE_BARRIER) { \
408  .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
409  .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
410  .Transition = { \
411  .pResource = res, \
412  .Subresource = subres, \
413  .StateBefore = before, \
414  .StateAfter = after, \
415  }, \
416  }
417 
418  barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
419  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
420  D3D12_RESOURCE_STATE_COMMON,
421  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
422  barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
423  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
424  D3D12_RESOURCE_STATE_COMMON,
425  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
426  barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
427  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
428  D3D12_RESOURCE_STATE_COMMON,
429  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
430  barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
431  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
432  D3D12_RESOURCE_STATE_COMMON,
433  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
434 
435  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
436 
437  if (ctx->is_texture_array)
438  barriers_ref = av_calloc(base_ctx->recon_frames->initial_pool_size * ctx->plane_count,
439  sizeof(D3D12_RESOURCE_BARRIER));
440  else
441  barriers_ref = av_calloc(MAX_DPB_SIZE, sizeof(D3D12_RESOURCE_BARRIER));
442 
443  if (ctx->is_texture_array) {
444  D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
445  pic->recon_surface->texture->lpVtbl->GetDesc(pic->recon_surface->texture, &references_tex_array_desc);
446 
447  for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
448  reference_subresource++) {
449 
450  uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
451  uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
452  uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
453 
454  for (uint32_t plane_slice = 0; plane_slice < ctx->plane_count; plane_slice++) {
455  uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
456  plane_slice * references_tex_array_desc.MipLevels * array_size;
457  if (reference_subresource == pic->subresource_index) {
458  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
459  D3D12_RESOURCE_STATE_COMMON,
460  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
461  } else {
462  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
463  D3D12_RESOURCE_STATE_COMMON,
464  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
465  }
466  }
467  }
468  } else {
469  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture,
470  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
471  D3D12_RESOURCE_STATE_COMMON,
472  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
473 
474  if (d3d12_refs.NumTexture2Ds) {
475  for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
476  barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
477  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
478  D3D12_RESOURCE_STATE_COMMON,
479  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
480  }
481  }
482  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
483 
484  ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list, ctx->encoder, ctx->encoder_heap,
485  &input_args, &output_args);
486 
487  barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
488  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
489  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
490  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
491 
492  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 1, &barriers[3]);
493 
494  ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
495 
496  if (barriers_ref_index > 0) {
497  for (i = 0; i < barriers_ref_index; i++)
498  FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[i].Transition.StateBefore, barriers_ref[i].Transition.StateAfter);
499 
500  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
501  barriers_ref);
502  }
503 
504  barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
505  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
506  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
507  D3D12_RESOURCE_STATE_COMMON);
508  barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
509  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
510  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
511  D3D12_RESOURCE_STATE_COMMON);
512  barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
513  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
514  D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
515  D3D12_RESOURCE_STATE_COMMON);
516  barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
517  D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
518  D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
519  D3D12_RESOURCE_STATE_COMMON);
520 
521  ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
522 
523  hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
524  if (FAILED(hr)) {
525  err = AVERROR_UNKNOWN;
526  goto fail;
527  }
528 
529  hr = ID3D12CommandQueue_Wait(ctx->command_queue, pic->input_surface->sync_ctx.fence,
531  if (FAILED(hr)) {
532  err = AVERROR_UNKNOWN;
533  goto fail;
534  }
535 
536  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
537 
538  hr = ID3D12CommandQueue_Signal(ctx->command_queue, pic->input_surface->sync_ctx.fence,
540  if (FAILED(hr)) {
541  err = AVERROR_UNKNOWN;
542  goto fail;
543  }
544 
545  hr = ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value);
546  if (FAILED(hr)) {
547  err = AVERROR_UNKNOWN;
548  goto fail;
549  }
550 
551  err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
552  if (err < 0)
553  goto fail;
554 
555  pic->fence_value = ctx->sync_ctx.fence_value;
556 
557  // Update intra refresh frame index for next frame
558  if (ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
559  ctx->intra_refresh_frame_index =
560  (ctx->intra_refresh_frame_index + 1) % ctx->intra_refresh.IntraRefreshDuration;
561  }
562 
563  if (d3d12_refs.ppTexture2Ds)
564  av_freep(&d3d12_refs.ppTexture2Ds);
565 
566  if (ctx->is_texture_array && d3d12_refs.pSubresources)
567  av_freep(&d3d12_refs.pSubresources);
568 
569  if (barriers_ref)
570  av_freep(&barriers_ref);
571 
572  return 0;
573 
574 fail:
575  if (command_allocator)
576  d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
577 
578  if (d3d12_refs.ppTexture2Ds)
579  av_freep(&d3d12_refs.ppTexture2Ds);
580 
581  if (ctx->is_texture_array && d3d12_refs.pSubresources)
582  av_freep(&d3d12_refs.pSubresources);
583 
584  if (barriers_ref)
585  av_freep(&barriers_ref);
586 
587  if (ctx->codec->free_picture_params)
588  ctx->codec->free_picture_params(pic);
589 
591  pic->output_buffer = NULL;
594  return err;
595 }
596 
598  FFHWBaseEncodePicture *base_pic)
599 {
600  D3D12VAEncodePicture *pic = base_pic->priv;
601 
602  d3d12va_encode_wait(avctx, base_pic);
603 
604  if (pic->output_buffer_ref) {
605  av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
606  "%"PRId64"/%"PRId64".\n",
607  base_pic->display_order, base_pic->encode_order);
608 
610  pic->output_buffer = NULL;
611  }
612 
615 
616  return 0;
617 }
618 
620 {
622 
623  switch (ctx->rc.Mode)
624  {
625  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP:
626  av_freep(&ctx->rc.ConfigParams.pConfiguration_CQP);
627  break;
628  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR:
629  av_freep(&ctx->rc.ConfigParams.pConfiguration_CBR);
630  break;
631  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR:
632  av_freep(&ctx->rc.ConfigParams.pConfiguration_VBR);
633  break;
634  case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR:
635  av_freep(&ctx->rc.ConfigParams.pConfiguration_QVBR);
636  break;
637  default:
638  break;
639  }
640 
641  return 0;
642 }
643 
645 {
647  D3D12VAEncodePicture *priv = pic->priv;
648  AVFrame *frame = pic->input_image;
649 
650  if (ctx->codec->picture_priv_data_size > 0) {
651  pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
652  if (!pic->codec_priv)
653  return AVERROR(ENOMEM);
654  }
655 
656  priv->input_surface = (AVD3D12VAFrame *)frame->data[0];
657 
658  return 0;
659 }
660 
662 {
664  D3D12VAEncodePicture *priv = pic->priv;
665 
666  if (pic->encode_issued)
667  d3d12va_encode_discard(avctx, pic);
668 
669  if (ctx->codec->free_picture_params)
670  ctx->codec->free_picture_params(priv);
671 
672  return 0;
673 }
674 
676  D3D12VAEncodePicture *pic, size_t *size)
677 {
678  D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta = NULL;
679  uint8_t *data;
680  HRESULT hr;
681  int err;
682 
683  hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
684  if (FAILED(hr)) {
685  err = AVERROR_UNKNOWN;
686  return err;
687  }
688 
689  meta = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)data;
690 
691  if (meta->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
692  av_log(avctx, AV_LOG_ERROR, "Encode failed %"PRIu64"\n", meta->EncodeErrorFlags);
693  err = AVERROR(EINVAL);
694  return err;
695  }
696 
697  if (meta->EncodedBitstreamWrittenBytesCount == 0) {
698  av_log(avctx, AV_LOG_ERROR, "No bytes were written to encoded bitstream\n");
699  err = AVERROR(EINVAL);
700  return err;
701  }
702 
703  *size = meta->EncodedBitstreamWrittenBytesCount;
704 
705  ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
706 
707  return 0;
708 }
709 
712 {
713  int err;
714  uint8_t *ptr, *mapped_data;
715  size_t total_size = 0;
716  HRESULT hr;
717 
718  err = d3d12va_encode_get_buffer_size(avctx, pic, &total_size);
719  if (err < 0)
720  goto end;
721 
722  total_size += pic->header_size;
723  av_log(avctx, AV_LOG_DEBUG, "Output buffer size %zu\n", total_size);
724 
725  hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&mapped_data);
726  if (FAILED(hr)) {
727  err = AVERROR_UNKNOWN;
728  goto end;
729  }
730 
731  err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
732  if (err < 0)
733  goto end;
734  ptr = pkt->data;
735 
736  memcpy(ptr, mapped_data, pic->header_size);
737 
738  ptr += pic->header_size;
739  mapped_data += pic->aligned_header_size;
740  total_size -= pic->header_size;
741 
742  memcpy(ptr, mapped_data, total_size);
743 
744  ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
745 
746 end:
748  pic->output_buffer = NULL;
749  return err;
750 }
751 
753  FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
754 {
756  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
757  D3D12VAEncodePicture *pic = base_pic->priv;
758  AVPacket *pkt_ptr = pkt;
759  int err = 0;
760 
761  err = d3d12va_encode_wait(avctx, base_pic);
762  if (err < 0)
763  return err;
764 
765  if (ctx->codec->get_coded_data)
766  err = ctx->codec->get_coded_data(avctx, pic, pkt);
767  else
768  err = d3d12va_encode_get_coded_data(avctx, pic, pkt);
769 
770  if (err < 0)
771  return err;
772 
773  av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
774  base_pic->display_order, base_pic->encode_order);
775 
777  pkt_ptr, 0);
778 
779  return 0;
780 }
781 
783 {
784  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
787  const AVPixFmtDescriptor *desc;
788  int i, depth;
789 
791  if (!desc) {
792  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
793  base_ctx->input_frames->sw_format);
794  return AVERROR(EINVAL);
795  }
796 
797  depth = desc->comp[0].depth;
798  for (i = 1; i < desc->nb_components; i++) {
799  if (desc->comp[i].depth != depth) {
800  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
801  desc->name);
802  return AVERROR(EINVAL);
803  }
804  }
805  av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
806  desc->name);
807 
808  av_assert0(ctx->codec->profiles);
809  for (i = 0; (ctx->codec->profiles[i].av_profile !=
810  AV_PROFILE_UNKNOWN); i++) {
811  profile = &ctx->codec->profiles[i];
812  if (depth != profile->depth ||
813  desc->nb_components != profile->nb_components)
814  continue;
815  if (desc->nb_components > 1 &&
816  (desc->log2_chroma_w != profile->log2_chroma_w ||
817  desc->log2_chroma_h != profile->log2_chroma_h))
818  continue;
819  if (avctx->profile != profile->av_profile &&
820  avctx->profile != AV_PROFILE_UNKNOWN)
821  continue;
822 
823  ctx->profile = profile;
824  break;
825  }
826  if (!ctx->profile) {
827  av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
828  return AVERROR(ENOSYS);
829  }
830 
831  avctx->profile = profile->av_profile;
832  return 0;
833 }
834 
836  // Bitrate Quality
837  // | Maxrate | HRD/VBV
838  { 0 }, // | | | |
839  { RC_MODE_CQP, "CQP", 0, 0, 1, 0, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP },
840  { RC_MODE_CBR, "CBR", 1, 0, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR },
841  { RC_MODE_VBR, "VBR", 1, 1, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR },
842  { RC_MODE_QVBR, "QVBR", 1, 1, 1, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR },
843 };
844 
846 {
847  HRESULT hr;
849  D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE d3d12_rc_mode = {
850  .Codec = ctx->codec->d3d12_codec,
851  };
852 
853  if (!rc_mode->d3d12_mode)
854  return 0;
855 
856  d3d12_rc_mode.IsSupported = 0;
857  d3d12_rc_mode.RateControlMode = rc_mode->d3d12_mode;
858 
859  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
860  D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE,
861  &d3d12_rc_mode, sizeof(d3d12_rc_mode));
862  if (FAILED(hr)) {
863  av_log(avctx, AV_LOG_ERROR, "Failed to check rate control support.\n");
864  return 0;
865  }
866 
867  return d3d12_rc_mode.IsSupported;
868 }
869 
871 {
873  int64_t rc_target_bitrate;
874  int64_t rc_peak_bitrate;
875  int rc_quality;
876  int64_t hrd_buffer_size;
877  int64_t hrd_initial_buffer_fullness;
878  int fr_num, fr_den;
880 
881 #define SET_QP_RANGE(ctl) do { \
882  if (avctx->qmin > 0 || avctx->qmax > 0) { \
883  ctl->MinQP = avctx->qmin; \
884  ctl->MaxQP = avctx->qmax; \
885  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_QP_RANGE; \
886  } \
887  } while(0)
888 
889 #define SET_MAX_FRAME_SIZE(ctl) do { \
890  if (ctx->max_frame_size > 0) { \
891  ctl->MaxFrameBitSize = ctx->max_frame_size * 8; \
892  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_MAX_FRAME_SIZE; \
893  } \
894  } while(0)
895 
896  // Rate control mode selection:
897  // * If the user has set a mode explicitly with the rc_mode option,
898  // use it and fail if it is not available.
899  // * If an explicit QP option has been set, use CQP.
900  // * If the codec is CQ-only, use CQP.
901  // * If the QSCALE avcodec option is set, use CQP.
902  // * If bitrate and quality are both set, try QVBR.
903  // * If quality is set, try CQP.
904  // * If bitrate and maxrate are set and have the same value, try CBR.
905  // * If a bitrate is set, try VBR, then CBR.
906  // * If no bitrate is set, try CQP.
907 
908 #define TRY_RC_MODE(mode, fail) do { \
909  rc_mode = &d3d12va_encode_rc_modes[mode]; \
910  if (!(rc_mode->d3d12_mode && check_rate_control_support(avctx, rc_mode))) { \
911  if (fail) { \
912  av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
913  "RC mode.\n", rc_mode->name); \
914  return AVERROR(EINVAL); \
915  } \
916  av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
917  "RC mode.\n", rc_mode->name); \
918  rc_mode = NULL; \
919  } else { \
920  goto rc_mode_found; \
921  } \
922  } while (0)
923 
924  if (ctx->explicit_rc_mode)
925  TRY_RC_MODE(ctx->explicit_rc_mode, 1);
926 
927  if (ctx->explicit_qp)
929 
932 
933  if (avctx->flags & AV_CODEC_FLAG_QSCALE)
935 
936  if (avctx->bit_rate > 0 && avctx->global_quality > 0)
938 
939  if (avctx->global_quality > 0) {
941  }
942 
943  if (avctx->bit_rate > 0 && avctx->rc_max_rate == avctx->bit_rate)
945 
946  if (avctx->bit_rate > 0) {
949  } else {
951  }
952 
953  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
954  "RC mode compatible with selected options.\n");
955  return AVERROR(EINVAL);
956 
957 rc_mode_found:
958  if (rc_mode->bitrate) {
959  if (avctx->bit_rate <= 0) {
960  av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s "
961  "RC mode.\n", rc_mode->name);
962  return AVERROR(EINVAL);
963  }
964 
965  if (rc_mode->maxrate) {
966  if (avctx->rc_max_rate > 0) {
967  if (avctx->rc_max_rate < avctx->bit_rate) {
968  av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: "
969  "bitrate (%"PRId64") must not be greater than "
970  "maxrate (%"PRId64").\n", avctx->bit_rate,
971  avctx->rc_max_rate);
972  return AVERROR(EINVAL);
973  }
974  rc_target_bitrate = avctx->bit_rate;
975  rc_peak_bitrate = avctx->rc_max_rate;
976  } else {
977  // We only have a target bitrate, but this mode requires
978  // that a maximum rate be supplied as well. Since the
979  // user does not want this to be a constraint, arbitrarily
980  // pick a maximum rate of double the target rate.
981  rc_target_bitrate = avctx->bit_rate;
982  rc_peak_bitrate = 2 * avctx->bit_rate;
983  }
984  } else {
985  if (avctx->rc_max_rate > avctx->bit_rate) {
986  av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored "
987  "in %s RC mode.\n", rc_mode->name);
988  }
989  rc_target_bitrate = avctx->bit_rate;
990  rc_peak_bitrate = 0;
991  }
992  } else {
993  rc_target_bitrate = 0;
994  rc_peak_bitrate = 0;
995  }
996 
997  if (rc_mode->quality) {
998  if (ctx->explicit_qp) {
999  rc_quality = ctx->explicit_qp;
1000  } else if (avctx->global_quality > 0) {
1001  if (avctx->flags & AV_CODEC_FLAG_QSCALE)
1002  rc_quality = avctx->global_quality / FF_QP2LAMBDA;
1003  else
1004  rc_quality = avctx->global_quality;
1005  } else {
1006  rc_quality = ctx->codec->default_quality;
1007  av_log(avctx, AV_LOG_WARNING, "No quality level set; "
1008  "using default (%d).\n", rc_quality);
1009  }
1010  } else {
1011  rc_quality = 0;
1012  }
1013 
1014  if (rc_mode->hrd) {
1015  if (avctx->rc_buffer_size)
1016  hrd_buffer_size = avctx->rc_buffer_size;
1017  else if (avctx->rc_max_rate > 0)
1018  hrd_buffer_size = avctx->rc_max_rate;
1019  else
1020  hrd_buffer_size = avctx->bit_rate;
1021  if (avctx->rc_initial_buffer_occupancy) {
1022  if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1023  av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1024  "must have initial buffer size (%d) <= "
1025  "buffer size (%"PRId64").\n",
1026  avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1027  return AVERROR(EINVAL);
1028  }
1029  hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1030  } else {
1031  hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1032  }
1033  } else {
1034  if (avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
1035  av_log(avctx, AV_LOG_WARNING, "Buffering settings are ignored "
1036  "in %s RC mode.\n", rc_mode->name);
1037  }
1038 
1039  hrd_buffer_size = 0;
1040  hrd_initial_buffer_fullness = 0;
1041  }
1042 
1043  if (rc_target_bitrate > UINT32_MAX ||
1044  hrd_buffer_size > UINT32_MAX ||
1045  hrd_initial_buffer_fullness > UINT32_MAX) {
1046  av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1047  "greater are not supported by D3D12.\n");
1048  return AVERROR(EINVAL);
1049  }
1050 
1051  ctx->rc_quality = rc_quality;
1052 
1053  av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s.\n", rc_mode->name);
1054 
1055  if (rc_mode->quality)
1056  av_log(avctx, AV_LOG_VERBOSE, "RC quality: %d.\n", rc_quality);
1057 
1058  if (rc_mode->hrd) {
1059  av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1060  "initial fullness %"PRId64" bits.\n",
1061  hrd_buffer_size, hrd_initial_buffer_fullness);
1062  }
1063 
1064  if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1065  av_reduce(&fr_num, &fr_den,
1066  avctx->framerate.num, avctx->framerate.den, 65535);
1067  else
1068  av_reduce(&fr_num, &fr_den,
1069  avctx->time_base.den, avctx->time_base.num, 65535);
1070 
1071  av_log(avctx, AV_LOG_VERBOSE, "RC framerate: %d/%d (%.2f fps).\n",
1072  fr_num, fr_den, (double)fr_num / fr_den);
1073 
1074  ctx->rc.Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
1075  ctx->rc.TargetFrameRate.Numerator = fr_num;
1076  ctx->rc.TargetFrameRate.Denominator = fr_den;
1077  ctx->rc.Mode = rc_mode->d3d12_mode;
1078 
1079  switch (rc_mode->mode) {
1080  case RC_MODE_CQP:
1081  // cqp ConfigParams will be updated in ctx->codec->configure.
1082  break;
1083  case RC_MODE_CBR: {
1084  D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR *cbr_ctl;
1085 
1086  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR);
1087  cbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1088  if (!cbr_ctl)
1089  return AVERROR(ENOMEM);
1090 
1091  cbr_ctl->TargetBitRate = rc_target_bitrate;
1092  cbr_ctl->VBVCapacity = hrd_buffer_size;
1093  cbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1094  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1095 
1096  SET_QP_RANGE(cbr_ctl);
1097  SET_MAX_FRAME_SIZE(cbr_ctl);
1098 
1099  ctx->rc.ConfigParams.pConfiguration_CBR = cbr_ctl;
1100  break;
1101  }
1102  case RC_MODE_VBR: {
1103  D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR *vbr_ctl;
1104 
1105  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR);
1106  vbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1107  if (!vbr_ctl)
1108  return AVERROR(ENOMEM);
1109 
1110  vbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1111  vbr_ctl->PeakBitRate = rc_peak_bitrate;
1112  vbr_ctl->VBVCapacity = hrd_buffer_size;
1113  vbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1114  ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1115 
1116  SET_QP_RANGE(vbr_ctl);
1117  SET_MAX_FRAME_SIZE(vbr_ctl);
1118 
1119  ctx->rc.ConfigParams.pConfiguration_VBR = vbr_ctl;
1120  break;
1121  }
1122  case RC_MODE_QVBR: {
1123  D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR *qvbr_ctl;
1124 
1125  ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR);
1126  qvbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1127  if (!qvbr_ctl)
1128  return AVERROR(ENOMEM);
1129 
1130  qvbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1131  qvbr_ctl->PeakBitRate = rc_peak_bitrate;
1132  qvbr_ctl->ConstantQualityTarget = rc_quality;
1133 
1134  SET_QP_RANGE(qvbr_ctl);
1135  SET_MAX_FRAME_SIZE(qvbr_ctl);
1136 
1137  ctx->rc.ConfigParams.pConfiguration_QVBR = qvbr_ctl;
1138  break;
1139  }
1140  default:
1141  break;
1142  }
1143  return 0;
1144 }
1145 
1147 {
1148  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1150  uint32_t ref_l0, ref_l1;
1151  int err;
1152  HRESULT hr;
1153  D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT support;
1154  union {
1155  D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
1156  D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
1157 #if CONFIG_AV1_D3D12VA_ENCODER
1158  D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
1159 #endif
1160  } codec_support;
1161 
1162  support.NodeIndex = 0;
1163  support.Codec = ctx->codec->d3d12_codec;
1164  support.Profile = ctx->profile->d3d12_profile;
1165 
1166  switch (ctx->codec->d3d12_codec) {
1167  case D3D12_VIDEO_ENCODER_CODEC_H264:
1168  support.PictureSupport.DataSize = sizeof(codec_support.h264);
1169  support.PictureSupport.pH264Support = &codec_support.h264;
1170  break;
1171 
1172  case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1173  support.PictureSupport.DataSize = sizeof(codec_support.hevc);
1174  support.PictureSupport.pHEVCSupport = &codec_support.hevc;
1175  break;
1176 
1177 #if CONFIG_AV1_D3D12VA_ENCODER
1178  case D3D12_VIDEO_ENCODER_CODEC_AV1:
1179  memset(&codec_support.av1, 0, sizeof(codec_support.av1));
1180  support.PictureSupport.DataSize = sizeof(codec_support.av1);
1181  support.PictureSupport.pAV1Support = &codec_support.av1;
1182  break;
1183 #endif
1184  default:
1185  av_assert0(0);
1186  }
1187 
1188  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1189  &support, sizeof(support));
1190  if (FAILED(hr))
1191  return AVERROR(EINVAL);
1192 
1193  if (support.IsSupported) {
1194  switch (ctx->codec->d3d12_codec) {
1195  case D3D12_VIDEO_ENCODER_CODEC_H264:
1196  ref_l0 = FFMIN(support.PictureSupport.pH264Support->MaxL0ReferencesForP,
1197  support.PictureSupport.pH264Support->MaxL1ReferencesForB ?
1198  support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX);
1199  ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB;
1200  break;
1201 
1202  case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1203  ref_l0 = FFMIN(support.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
1204  support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB ?
1205  support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX);
1206  ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
1207  break;
1208 
1209 #if CONFIG_AV1_D3D12VA_ENCODER
1210  case D3D12_VIDEO_ENCODER_CODEC_AV1:
1211  ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
1212  // AV1 doesn't use traditional L1 references like H.264/HEVC
1213  ref_l1 = 0;
1214  break;
1215 #endif
1216  default:
1217  av_assert0(0);
1218  }
1219  } else {
1220  ref_l0 = ref_l1 = 0;
1221  }
1222 
1223  if (ref_l0 > 0 && ref_l1 > 0 && ctx->bi_not_empty) {
1224  base_ctx->p_to_gpb = 1;
1225  av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, "
1226  "replacing them with B-frames.\n");
1227  }
1228 
1229  err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1, ctx->codec->flags, 0);
1230  if (err < 0)
1231  return err;
1232 
1233  return 0;
1234 }
1235 
1237 {
1238  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1240 
1241  if (ctx->intra_refresh.Mode == D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE)
1242  return 0;
1243 
1244  // Check for SDK API availability
1245 #if CONFIG_D3D12_INTRA_REFRESH
1246  HRESULT hr;
1247  D3D12_VIDEO_ENCODER_LEVEL_SETTING level = { 0 };
1248  D3D12_VIDEO_ENCODER_LEVELS_H264 h264_level = { 0 };
1249  D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevc_level = { 0 };
1250 #if CONFIG_AV1_D3D12VA_ENCODER
1251  D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1_level = { 0 };
1252 #endif
1253 
1254  switch (ctx->codec->d3d12_codec) {
1255  case D3D12_VIDEO_ENCODER_CODEC_H264:
1256  level.DataSize = sizeof(D3D12_VIDEO_ENCODER_LEVELS_H264);
1257  level.pH264LevelSetting = &h264_level;
1258  break;
1259  case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1260  level.DataSize = sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
1261  level.pHEVCLevelSetting = &hevc_level;
1262  break;
1263 #if CONFIG_AV1_D3D12VA_ENCODER
1264  case D3D12_VIDEO_ENCODER_CODEC_AV1:
1265  level.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1266  level.pAV1LevelSetting = &av1_level;
1267  break;
1268 #endif
1269  default:
1270  av_assert0(0);
1271  }
1272 
1273  D3D12_FEATURE_DATA_VIDEO_ENCODER_INTRA_REFRESH_MODE intra_refresh_support = {
1274  .NodeIndex = 0,
1275  .Codec = ctx->codec->d3d12_codec,
1276  .Profile = ctx->profile->d3d12_profile,
1277  .Level = level,
1278  .IntraRefreshMode = ctx->intra_refresh.Mode,
1279  };
1280 
1281  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1282  D3D12_FEATURE_VIDEO_ENCODER_INTRA_REFRESH_MODE,
1283  &intra_refresh_support, sizeof(intra_refresh_support));
1284 
1285  if (FAILED(hr) || !intra_refresh_support.IsSupported) {
1286  av_log(avctx, AV_LOG_ERROR, "Requested intra refresh mode not supported by driver.\n");
1287  return AVERROR(ENOTSUP);
1288  }
1289 #else
1290  // Older SDK - validation will occur in init_sequence_params via D3D12_FEATURE_VIDEO_ENCODER_SUPPORT
1291  av_log(avctx, AV_LOG_VERBOSE, "Intra refresh explicit check not available in this SDK.\n"
1292  "Support will be validated during encoder initialization.\n");
1293 #endif
1294 
1295  // Set duration: use GOP size if not specified
1296  if (ctx->intra_refresh.IntraRefreshDuration == 0) {
1297  ctx->intra_refresh.IntraRefreshDuration = base_ctx->gop_size;
1298  av_log(avctx, AV_LOG_VERBOSE, "Intra refresh duration set to GOP size: %d\n",
1299  ctx->intra_refresh.IntraRefreshDuration);
1300  }
1301 
1302  // Initialize frame index
1303  ctx->intra_refresh_frame_index = 0;
1304 
1305  av_log(avctx, AV_LOG_VERBOSE, "Intra refresh: mode=%d, duration=%d frames\n",
1306  ctx->intra_refresh.Mode, ctx->intra_refresh.IntraRefreshDuration);
1307 
1308  return 0;
1309 }
1310 
1312 {
1313  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1315  AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
1316  HRESULT hr;
1317 
1318  D3D12_VIDEO_ENCODER_DESC desc = {
1319  .NodeMask = 0,
1320  .Flags = D3D12_VIDEO_ENCODER_FLAG_NONE,
1321  .EncodeCodec = ctx->codec->d3d12_codec,
1322  .EncodeProfile = ctx->profile->d3d12_profile,
1323  .InputFormat = frames_hwctx->format,
1324  .CodecConfiguration = ctx->codec_conf,
1325  .MaxMotionEstimationPrecision = D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM,
1326  };
1327 
1328  hr = ID3D12VideoDevice3_CreateVideoEncoder(ctx->video_device3, &desc, &IID_ID3D12VideoEncoder,
1329  (void **)&ctx->encoder);
1330  if (FAILED(hr)) {
1331  av_log(avctx, AV_LOG_ERROR, "Failed to create encoder.\n");
1332  return AVERROR(EINVAL);
1333  }
1334 
1335  return 0;
1336 }
1337 
1339 {
1341  HRESULT hr;
1342 
1343  D3D12_VIDEO_ENCODER_HEAP_DESC desc = {
1344  .NodeMask = 0,
1345  .Flags = D3D12_VIDEO_ENCODER_HEAP_FLAG_NONE,
1346  .EncodeCodec = ctx->codec->d3d12_codec,
1347  .EncodeProfile = ctx->profile->d3d12_profile,
1348  .EncodeLevel = ctx->level,
1349  .ResolutionsListCount = 1,
1350  .pResolutionList = &ctx->resolution,
1351  };
1352 
1353  hr = ID3D12VideoDevice3_CreateVideoEncoderHeap(ctx->video_device3, &desc,
1354  &IID_ID3D12VideoEncoderHeap, (void **)&ctx->encoder_heap);
1355  if (FAILED(hr)) {
1356  av_log(avctx, AV_LOG_ERROR, "Failed to create encoder heap.\n");
1357  return AVERROR(EINVAL);
1358  }
1359 
1360  return 0;
1361 }
1362 
1363 static void d3d12va_encode_free_buffer(void *opaque, uint8_t *data)
1364 {
1365  ID3D12Resource *pResource;
1366 
1367  pResource = (ID3D12Resource *)data;
1368  D3D12_OBJECT_RELEASE(pResource);
1369 }
1370 
1372 {
1373  AVCodecContext *avctx = opaque;
1374  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1376  ID3D12Resource *pResource = NULL;
1377  HRESULT hr;
1378  AVBufferRef *ref;
1379  D3D12_HEAP_PROPERTIES heap_props;
1380  D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_READBACK;
1381 
1382  D3D12_RESOURCE_DESC desc = {
1383  .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1384  .Alignment = 0,
1385  .Width = FFALIGN(3 * base_ctx->surface_width * base_ctx->surface_height + (1 << 16),
1386  D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT),
1387  .Height = 1,
1388  .DepthOrArraySize = 1,
1389  .MipLevels = 1,
1390  .Format = DXGI_FORMAT_UNKNOWN,
1391  .SampleDesc = { .Count = 1, .Quality = 0 },
1392  .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1393  .Flags = D3D12_RESOURCE_FLAG_NONE,
1394  };
1395 
1396  ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(ctx->hwctx->device, &heap_props, 0, heap_type);
1397 
1398  hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
1399  &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource,
1400  (void **)&pResource);
1401 
1402  if (FAILED(hr)) {
1403  av_log(avctx, AV_LOG_ERROR, "Failed to create d3d12 buffer.\n");
1404  return NULL;
1405  }
1406 
1407  ref = av_buffer_create((uint8_t *)(uintptr_t)pResource,
1408  sizeof(pResource),
1410  avctx, AV_BUFFER_FLAG_READONLY);
1411  if (!ref) {
1412  D3D12_OBJECT_RELEASE(pResource);
1413  return NULL;
1414  }
1415 
1416  return ref;
1417 }
1418 
1420 {
1421  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1423  AVD3D12VAFramesContext *frames_ctx = base_ctx->input_frames->hwctx;
1424  HRESULT hr;
1425 
1426  ctx->req.NodeIndex = 0;
1427  ctx->req.Codec = ctx->codec->d3d12_codec;
1428  ctx->req.Profile = ctx->profile->d3d12_profile;
1429  ctx->req.InputFormat = frames_ctx->format;
1430  ctx->req.PictureTargetResolution = ctx->resolution;
1431 
1432  hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1433  D3D12_FEATURE_VIDEO_ENCODER_RESOURCE_REQUIREMENTS,
1434  &ctx->req, sizeof(ctx->req));
1435  if (FAILED(hr)) {
1436  av_log(avctx, AV_LOG_ERROR, "Failed to check encoder resource requirements support.\n");
1437  return AVERROR(EINVAL);
1438  }
1439 
1440  if (!ctx->req.IsSupported) {
1441  av_log(avctx, AV_LOG_ERROR, "Encoder resource requirements unsupported.\n");
1442  return AVERROR(EINVAL);
1443  }
1444 
1445  ctx->output_buffer_pool = av_buffer_pool_init2(sizeof(ID3D12Resource *), avctx,
1447  if (!ctx->output_buffer_pool)
1448  return AVERROR(ENOMEM);
1449 
1450  return 0;
1451 }
1452 
1454 {
1456  ID3D12CommandAllocator *command_allocator = NULL;
1457  int err = AVERROR_UNKNOWN;
1458  HRESULT hr;
1459 
1460  D3D12_COMMAND_QUEUE_DESC queue_desc = {
1461  .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
1462  .Priority = 0,
1463  .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
1464  .NodeMask = 0,
1465  };
1466 
1469  if (!ctx->allocator_queue)
1470  return AVERROR(ENOMEM);
1471 
1472  hr = ID3D12Device_CreateFence(ctx->hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
1473  &IID_ID3D12Fence, (void **)&ctx->sync_ctx.fence);
1474  if (FAILED(hr)) {
1475  av_log(avctx, AV_LOG_ERROR, "Failed to create fence(%lx)\n", (long)hr);
1476  err = AVERROR_UNKNOWN;
1477  goto fail;
1478  }
1479 
1480  ctx->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
1481  if (!ctx->sync_ctx.event)
1482  goto fail;
1483 
1484  err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
1485  if (err < 0)
1486  goto fail;
1487 
1488  hr = ID3D12Device_CreateCommandQueue(ctx->hwctx->device, &queue_desc,
1489  &IID_ID3D12CommandQueue, (void **)&ctx->command_queue);
1490  if (FAILED(hr)) {
1491  av_log(avctx, AV_LOG_ERROR, "Failed to create command queue(%lx)\n", (long)hr);
1492  err = AVERROR_UNKNOWN;
1493  goto fail;
1494  }
1495 
1496  hr = ID3D12Device_CreateCommandList(ctx->hwctx->device, 0, queue_desc.Type,
1497  command_allocator, NULL, &IID_ID3D12CommandList,
1498  (void **)&ctx->command_list);
1499  if (FAILED(hr)) {
1500  av_log(avctx, AV_LOG_ERROR, "Failed to create command list(%lx)\n", (long)hr);
1501  err = AVERROR_UNKNOWN;
1502  goto fail;
1503  }
1504 
1505  hr = ID3D12VideoEncodeCommandList2_Close(ctx->command_list);
1506  if (FAILED(hr)) {
1507  av_log(avctx, AV_LOG_ERROR, "Failed to close the command list(%lx)\n", (long)hr);
1508  err = AVERROR_UNKNOWN;
1509  goto fail;
1510  }
1511 
1512  ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
1513 
1514  err = d3d12va_sync_with_gpu(avctx);
1515  if (err < 0)
1516  goto fail;
1517 
1518  err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
1519  if (err < 0)
1520  goto fail;
1521 
1522  return 0;
1523 
1524 fail:
1525  D3D12_OBJECT_RELEASE(command_allocator);
1526  return err;
1527 }
1528 
1530 {
1531  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1533  AVD3D12VAFramesContext *hwctx;
1534  enum AVPixelFormat recon_format;
1535  int err;
1536 
1537  err = ff_hw_base_get_recon_format(base_ctx, NULL, &recon_format);
1538  if (err < 0)
1539  return err;
1540 
1541  base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref);
1542  if (!base_ctx->recon_frames_ref)
1543  return AVERROR(ENOMEM);
1544 
1545  base_ctx->recon_frames = (AVHWFramesContext *)base_ctx->recon_frames_ref->data;
1546  hwctx = (AVD3D12VAFramesContext *)base_ctx->recon_frames->hwctx;
1547 
1548  base_ctx->recon_frames->format = AV_PIX_FMT_D3D12;
1549  base_ctx->recon_frames->sw_format = recon_format;
1550  base_ctx->recon_frames->width = base_ctx->surface_width;
1551  base_ctx->recon_frames->height = base_ctx->surface_height;
1552 
1553  hwctx->resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
1554  D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1555  if (ctx->is_texture_array) {
1556  base_ctx->recon_frames->initial_pool_size = MAX_DPB_SIZE + 1;
1558  }
1559 
1560  err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
1561  if (err < 0) {
1562  av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
1563  "frame context: %d.\n", err);
1564  return err;
1565  }
1566 
1567  return 0;
1568 }
1569 
1571  .priv_size = sizeof(D3D12VAEncodePicture),
1572 
1574 
1575  .issue = &d3d12va_encode_issue,
1576 
1578 
1579  .free = &d3d12va_encode_free,
1580 };
1581 
1583 {
1584  return ff_hw_base_encode_receive_packet(avctx->priv_data, avctx, pkt);
1585 }
1586 
1588 {
1589  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1591  D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
1592  D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
1593  int err;
1594  HRESULT hr;
1595 
1596  err = ff_hw_base_encode_init(avctx, base_ctx);
1597  if (err < 0)
1598  goto fail;
1599 
1600  base_ctx->op = &d3d12va_type;
1601 
1602  ctx->hwctx = base_ctx->device->hwctx;
1603 
1604  ctx->resolution.Width = base_ctx->input_frames->width;
1605  ctx->resolution.Height = base_ctx->input_frames->height;
1606 
1607  hr = ID3D12Device_QueryInterface(ctx->hwctx->device, &IID_ID3D12Device3, (void **)&ctx->device3);
1608  if (FAILED(hr)) {
1609  av_log(avctx, AV_LOG_ERROR, "ID3D12Device3 interface is not supported.\n");
1610  err = AVERROR_UNKNOWN;
1611  goto fail;
1612  }
1613 
1614  hr = ID3D12Device3_QueryInterface(ctx->device3, &IID_ID3D12VideoDevice3, (void **)&ctx->video_device3);
1615  if (FAILED(hr)) {
1616  av_log(avctx, AV_LOG_ERROR, "ID3D12VideoDevice3 interface is not supported.\n");
1617  err = AVERROR_UNKNOWN;
1618  goto fail;
1619  }
1620 
1621  if (FAILED(ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1622  &support, sizeof(support))) && !support.VideoEncodeSupport) {
1623  av_log(avctx, AV_LOG_ERROR, "D3D12 video device has no video encoder support.\n");
1624  err = AVERROR(EINVAL);
1625  goto fail;
1626  }
1627 
1628  format_info.Format = ((AVD3D12VAFramesContext *)base_ctx->input_frames->hwctx)->format;
1629  if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
1630  &format_info, sizeof(format_info)))) {
1631  av_log(avctx, AV_LOG_ERROR, "Failed to query format plane count: %#lx\n", hr);
1632  err = AVERROR_EXTERNAL;
1633  goto fail;
1634  }
1635  ctx->plane_count = format_info.PlaneCount;
1636 
1637  err = d3d12va_encode_set_profile(avctx);
1638  if (err < 0)
1639  goto fail;
1640 
1641  if (ctx->codec->set_tile) {
1642  err = ctx->codec->set_tile(avctx);
1643  if (err < 0)
1644  goto fail;
1645  }
1646 
1647  err = d3d12va_encode_init_rate_control(avctx);
1648  if (err < 0)
1649  goto fail;
1650 
1651  if (ctx->codec->get_encoder_caps) {
1652  err = ctx->codec->get_encoder_caps(avctx);
1653  if (err < 0)
1654  goto fail;
1655  }
1656 
1657  err = d3d12va_encode_init_gop_structure(avctx);
1658  if (err < 0)
1659  goto fail;
1660 
1661  err = d3d12va_encode_init_intra_refresh(avctx);
1662  if (err < 0)
1663  goto fail;
1664 
1665  if (!(ctx->codec->flags & FF_HW_FLAG_SLICE_CONTROL) && avctx->slices > 0) {
1666  av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested "
1667  "but this codec does not support controlling slices.\n");
1668  }
1669 
1671  if (err < 0)
1672  goto fail;
1673 
1675  if (err < 0)
1676  goto fail;
1677 
1678  if (ctx->codec->configure) {
1679  err = ctx->codec->configure(avctx);
1680  if (err < 0)
1681  goto fail;
1682  }
1683 
1684  if (ctx->codec->init_sequence_params) {
1685  err = ctx->codec->init_sequence_params(avctx);
1686  if (err < 0) {
1687  av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
1688  "failed: %d.\n", err);
1689  goto fail;
1690  }
1691  }
1692 
1693  if (ctx->codec->set_level) {
1694  err = ctx->codec->set_level(avctx);
1695  if (err < 0)
1696  goto fail;
1697  }
1698 
1700  if (err < 0)
1701  goto fail;
1702 
1703  base_ctx->output_delay = base_ctx->b_per_p;
1704  base_ctx->decode_delay = base_ctx->max_b_depth;
1705 
1706  err = d3d12va_create_encoder(avctx);
1707  if (err < 0)
1708  goto fail;
1709 
1710  err = d3d12va_create_encoder_heap(avctx);
1711  if (err < 0)
1712  goto fail;
1713 
1714  base_ctx->async_encode = 1;
1715  base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
1716  sizeof(D3D12VAEncodePicture *), 0);
1717  if (!base_ctx->encode_fifo)
1718  return AVERROR(ENOMEM);
1719 
1720  return 0;
1721 
1722 fail:
1723  return err;
1724 }
1725 
1727 {
1728  int num_allocator = 0;
1729  FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1731  FFHWBaseEncodePicture *pic, *next;
1732  CommandAllocator allocator;
1733 
1734  if (!base_ctx->frame)
1735  return 0;
1736 
1737  for (pic = base_ctx->pic_start; pic; pic = next) {
1738  next = pic->next;
1739  d3d12va_encode_free(avctx, pic);
1740  }
1741 
1743 
1744  av_buffer_pool_uninit(&ctx->output_buffer_pool);
1745 
1746  D3D12_OBJECT_RELEASE(ctx->command_list);
1747  D3D12_OBJECT_RELEASE(ctx->command_queue);
1748 
1749  if (ctx->allocator_queue) {
1750  while (av_fifo_read(ctx->allocator_queue, &allocator, 1) >= 0) {
1751  num_allocator++;
1753  }
1754 
1755  av_log(avctx, AV_LOG_VERBOSE, "Total number of command allocators reused: %d\n", num_allocator);
1756  }
1757 
1758  av_fifo_freep2(&ctx->allocator_queue);
1759 
1760  D3D12_OBJECT_RELEASE(ctx->sync_ctx.fence);
1761  if (ctx->sync_ctx.event)
1762  CloseHandle(ctx->sync_ctx.event);
1763 
1764  D3D12_OBJECT_RELEASE(ctx->encoder_heap);
1765  D3D12_OBJECT_RELEASE(ctx->encoder);
1766  D3D12_OBJECT_RELEASE(ctx->video_device3);
1767  D3D12_OBJECT_RELEASE(ctx->device3);
1768 
1769  ff_hw_base_encode_close(base_ctx);
1770 
1771  return 0;
1772 }
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
level
uint8_t level
Definition: svq3.c:208
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:782
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:1529
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:710
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:559
d3d12va_encode_output
static int d3d12va_encode_output(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
Definition: d3d12va_encode.c:752
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:661
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:210
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:496
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:835
check_rate_control_support
static int check_rate_control_support(AVCodecContext *avctx, const D3D12VAEncodeRCMode *rc_mode)
Definition: d3d12va_encode.c:845
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:675
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:1306
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:1225
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:1338
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:597
AVCodecContext::rc_max_rate
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:1278
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
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:1263
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:489
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:543
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:1363
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:1453
ff_d3d12va_encode_init
int ff_d3d12va_encode_init(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1587
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:1570
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:1371
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:644
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
d3d12va_encode_init_intra_refresh
static int d3d12va_encode_init_intra_refresh(AVCodecContext *avctx)
Definition: d3d12va_encode.c:1236
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:1311
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:870
FFHWBaseEncodeContext::gop_size
int gop_size
Definition: hw_base_encode.h:184
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
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:1419
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:439
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:1626
d3d12va_encode_free_rc_params
static int d3d12va_encode_free_rc_params(AVCodecContext *avctx)
Definition: d3d12va_encode.c:619
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:1726
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::slices
int slices
Number of slices.
Definition: avcodec.h:1029
ff_d3d12va_encode_receive_packet
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
Definition: d3d12va_encode.c:1582
AVPacket
This structure stores compressed data.
Definition: packet.h:565
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:466
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:1146
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