FFmpeg
Loading...
Searching...
No Matches
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
41
43 D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags)
44{
45 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_CODEC_NOT_SUPPORTED)
46 av_log(log_ctx, AV_LOG_ERROR, " - Codec not supported\n");
47 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_INPUT_FORMAT_NOT_SUPPORTED)
48 av_log(log_ctx, AV_LOG_ERROR, " - Input format not supported\n");
49 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_CODEC_CONFIGURATION_NOT_SUPPORTED)
50 av_log(log_ctx, AV_LOG_ERROR, " - Codec configuration not supported\n");
51 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RATE_CONTROL_MODE_NOT_SUPPORTED)
52 av_log(log_ctx, AV_LOG_ERROR, " - Rate control mode not supported\n");
53 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RATE_CONTROL_CONFIGURATION_NOT_SUPPORTED)
54 av_log(log_ctx, AV_LOG_ERROR, " - Rate control configuration not supported\n");
55 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_INTRA_REFRESH_MODE_NOT_SUPPORTED)
56 av_log(log_ctx, AV_LOG_ERROR, " - Intra refresh mode not supported\n");
57 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_SUBREGION_LAYOUT_MODE_NOT_SUPPORTED)
58 av_log(log_ctx, AV_LOG_ERROR, " - Subregion layout mode not supported\n");
59 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_RESOLUTION_NOT_SUPPORTED_IN_LIST)
60 av_log(log_ctx, AV_LOG_ERROR, " - Resolution not supported\n");
61 if (flags & D3D12_VIDEO_ENCODER_VALIDATION_FLAG_GOP_STRUCTURE_NOT_SUPPORTED)
62 av_log(log_ctx, AV_LOG_ERROR, " - GOP structure not supported\n");
63}
64
66{
67 uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->fence);
68 if (completion < psync_ctx->fence_value) {
69 if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->fence, psync_ctx->fence_value, psync_ctx->event)))
70 return AVERROR(EINVAL);
71
72 WaitForSingleObjectEx(psync_ctx->event, INFINITE, FALSE);
73 }
74
75 return 0;
76}
77
79{
81
82 DX_CHECK(ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value));
83 return d3d12va_fence_completion(&ctx->sync_ctx);
84
85fail:
86 return AVERROR(EINVAL);
87}
88
89typedef struct CommandAllocator {
90 ID3D12CommandAllocator *command_allocator;
91 uint64_t fence_value;
93
94static int d3d12va_get_valid_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator)
95{
96 HRESULT hr;
98 CommandAllocator allocator;
99
100 if (av_fifo_peek(ctx->allocator_queue, &allocator, 1, 0) >= 0) {
101 uint64_t completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
102 if (completion >= allocator.fence_value) {
103 *ppAllocator = allocator.command_allocator;
104 av_fifo_read(ctx->allocator_queue, &allocator, 1);
105 return 0;
106 }
107 }
108
109 hr = ID3D12Device_CreateCommandAllocator(ctx->hwctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
110 &IID_ID3D12CommandAllocator, (void **)ppAllocator);
111 if (FAILED(hr)) {
112 av_log(avctx, AV_LOG_ERROR, "Failed to create a new command allocator!\n");
113 return AVERROR(EINVAL);
114 }
115
116 return 0;
117}
118
119static int d3d12va_discard_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator, uint64_t fence_value)
120{
122
123 CommandAllocator allocator = {
124 .command_allocator = pAllocator,
125 .fence_value = fence_value,
126 };
127
128 av_fifo_write(ctx->allocator_queue, &allocator, 1);
129
130 return 0;
131}
132
134 FFHWBaseEncodePicture *base_pic)
135{
137 D3D12VAEncodePicture *pic = base_pic->priv;
138 uint64_t completion;
139
140 av_assert0(base_pic->encode_issued);
141
142 if (base_pic->encode_complete) {
143 // Already waited for this picture.
144 return 0;
145 }
146
147 completion = ID3D12Fence_GetCompletedValue(ctx->sync_ctx.fence);
148 if (completion < pic->fence_value) {
149 if (FAILED(ID3D12Fence_SetEventOnCompletion(ctx->sync_ctx.fence, pic->fence_value,
150 ctx->sync_ctx.event)))
151 return AVERROR(EINVAL);
152
153 WaitForSingleObjectEx(ctx->sync_ctx.event, INFINITE, FALSE);
154 }
155
156 av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" "
157 "(input surface %p).\n", base_pic->display_order,
158 base_pic->encode_order, pic->input_surface->texture);
159
160 av_frame_free(&base_pic->input_image);
161
162 base_pic->encode_complete = 1;
163 return 0;
164}
165
168 const uint8_t *data, size_t size)
169{
171 const AVRegionOfInterest *roi;
172 uint32_t roi_size;
173 int nb_roi, i;
174 int block_width, block_height;
175 int block_size, qp_range;
176 int is_av1 = 0;
177
178 // Use the QP map region size reported by the driver
179 block_size = ctx->qp_map_region_size;
180
181 // Determine QP range and element size based on codec
182 switch (ctx->codec->d3d12_codec) {
183 case D3D12_VIDEO_ENCODER_CODEC_H264:
184 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
185 qp_range = 51;
186 is_av1 = 0;
187 break;
188#if CONFIG_AV1_D3D12VA_ENCODER
189 case D3D12_VIDEO_ENCODER_CODEC_AV1:
190 qp_range = 255;
191 is_av1 = 1;
192 break;
193#endif
194 default:
195 av_log(avctx, AV_LOG_ERROR, "Unsupported codec for ROI.\n");
196 return AVERROR(EINVAL);
197 }
198
199 // Calculate map dimensions using ceil division as required by D3D12
200 block_width = (avctx->width + block_size - 1) / block_size;
201 block_height = (avctx->height + block_size - 1) / block_size;
202
203 // Allocate QP map with correct type based on codec
204 if (is_av1) {
205 pic->qp_map = av_calloc(block_width * block_height, sizeof(int16_t));
206 } else {
207 pic->qp_map = av_calloc(block_width * block_height, sizeof(int8_t));
208 }
209 if (!pic->qp_map)
210 return AVERROR(ENOMEM);
211
212 // Process ROI regions
213 roi = (const AVRegionOfInterest *)data;
214 roi_size = roi->self_size;
215 av_assert0(roi_size && size % roi_size == 0);
216 nb_roi = size / roi_size;
217
218 // Iterate in reverse for priority (first region in array takes priority on overlap)
219 for (i = nb_roi - 1; i >= 0; i--) {
220 int startx, endx, starty, endy;
221 int delta_qp;
222 int x, y;
223
224 roi = (const AVRegionOfInterest *)(data + roi_size * i);
225
226 // Convert pixel coordinates to block coordinates
227 starty = FFMIN(block_height, roi->top / block_size);
228 endy = FFMIN(block_height, (roi->bottom + block_size - 1) / block_size);
229 startx = FFMIN(block_width, roi->left / block_size);
230 endx = FFMIN(block_width, (roi->right + block_size - 1) / block_size);
231
232 if (roi->qoffset.den == 0) {
233 av_freep(&pic->qp_map);
234 av_log(avctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n");
235 return AVERROR(EINVAL);
236 }
237
238 // Convert qoffset to delta QP
239 delta_qp = roi->qoffset.num * qp_range / roi->qoffset.den;
240
241 av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n",
242 roi->top, roi->left, roi->bottom, roi->right, delta_qp);
243
244 // Fill QP map for this ROI region with correct type
245 if (is_av1) {
246 int16_t *qp_map_int16 = (int16_t *)pic->qp_map;
247 delta_qp = av_clip_int16(delta_qp);
248 for (y = starty; y < endy; y++)
249 for (x = startx; x < endx; x++)
250 qp_map_int16[x + y * block_width] = delta_qp;
251 } else {
252 int8_t *qp_map_int8 = (int8_t *)pic->qp_map;
253 delta_qp = av_clip_int8(delta_qp);
254 for (y = starty; y < endy; y++)
255 for (x = startx; x < endx; x++)
256 qp_map_int8[x + y * block_width] = delta_qp;
257 }
258 }
259
260 pic->qp_map_size = block_width * block_height;
261
262 return 0;
263}
264
267{
269 int num_subregions = ctx->num_subregions > 0 ? ctx->num_subregions : 1;
270 int width = sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
271 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) * num_subregions;
272#if CONFIG_AV1_D3D12VA_ENCODER
273 if (ctx->codec->d3d12_codec == D3D12_VIDEO_ENCODER_CODEC_AV1) {
274 width += sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES)
275 + sizeof(D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES);
276 }
277#endif
278 D3D12_HEAP_PROPERTIES encoded_meta_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }, resolved_meta_props;
279 D3D12_HEAP_TYPE resolved_heap_type = D3D12_HEAP_TYPE_READBACK;
280 HRESULT hr;
281
282 D3D12_RESOURCE_DESC meta_desc = {
283 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
284 .Alignment = 0,
285 .Width = ctx->req.MaxEncoderOutputMetadataBufferSize,
286 .Height = 1,
287 .DepthOrArraySize = 1,
288 .MipLevels = 1,
289 .Format = DXGI_FORMAT_UNKNOWN,
290 .SampleDesc = { .Count = 1, .Quality = 0 },
291 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
292 .Flags = D3D12_RESOURCE_FLAG_NONE,
293 };
294
295 hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &encoded_meta_props, D3D12_HEAP_FLAG_NONE,
296 &meta_desc, D3D12_RESOURCE_STATE_COMMON, NULL,
297 &IID_ID3D12Resource, (void **)&pic->encoded_metadata);
298 if (FAILED(hr)) {
299 av_log(avctx, AV_LOG_ERROR, "Failed to create metadata buffer.\n");
300 return AVERROR_UNKNOWN;
301 }
302
303 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(ctx->hwctx->device, &resolved_meta_props, 0, resolved_heap_type);
304
305 meta_desc.Width = width;
306
307 hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &resolved_meta_props, D3D12_HEAP_FLAG_NONE,
308 &meta_desc, D3D12_RESOURCE_STATE_COMMON, NULL,
309 &IID_ID3D12Resource, (void **)&pic->resolved_metadata);
310
311 if (FAILED(hr)) {
312 av_log(avctx, AV_LOG_ERROR, "Failed to create output metadata buffer.\n");
313 return AVERROR_UNKNOWN;
314 }
315
316 return 0;
317}
318
320 FFHWBaseEncodePicture *base_pic)
321{
322 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
324 D3D12VAEncodePicture *pic = base_pic->priv;
325 AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
326 int err, i, j;
327 HRESULT hr;
329 void *ptr;
330 size_t bit_len;
331 ID3D12CommandAllocator *command_allocator = NULL;
332 ID3D12VideoEncodeCommandList2 *cmd_list = ctx->command_list;
333 D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
334 D3D12_VIDEO_ENCODE_REFERENCE_FRAMES d3d12_refs = { 0 };
335 int barriers_ref_index = 0;
336 D3D12_RESOURCE_BARRIER *barriers_ref = NULL;
337
338 D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAGS seq_flags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE;
339
340 // Request intra refresh if enabled
341 if (ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
342 seq_flags |= D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_REQUEST_INTRA_REFRESH;
343 }
344
345 D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
346 .SequenceControlDesc = {
347 .Flags = seq_flags,
348 .IntraRefreshConfig = ctx->intra_refresh,
349 .RateControl = ctx->rc,
350 .PictureTargetResolution = ctx->resolution,
351 .SelectedLayoutMode = ctx->subregion_mode,
352 .FrameSubregionsLayoutData = ctx->subregions_layout,
353 .CodecGopSequence = ctx->gop,
354 },
355 .pInputFrame = pic->input_surface->texture,
356 .InputFrameSubresource = 0,
357 };
358
359 D3D12_VIDEO_ENCODER_ENCODEFRAME_OUTPUT_ARGUMENTS output_args = { 0 };
360
361 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS input_metadata = {
362 .EncoderCodec = ctx->codec->d3d12_codec,
363 .EncoderProfile = ctx->profile->d3d12_profile,
364 .EncoderInputFormat = frames_hwctx->format,
365 .EncodedPictureEffectiveResolution = ctx->resolution,
366 };
367
368 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_OUTPUT_ARGUMENTS output_metadata = { 0 };
369
370 memset(data, 0, sizeof(data));
371
372 av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
373 "as type %s.\n", base_pic->display_order, base_pic->encode_order,
375 if (base_pic->nb_refs[0] == 0 && base_pic->nb_refs[1] == 0) {
376 av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
377 } else {
378 av_log(avctx, AV_LOG_DEBUG, "L0 refers to");
379 for (i = 0; i < base_pic->nb_refs[0]; i++) {
380 av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
381 base_pic->refs[0][i]->display_order, base_pic->refs[0][i]->encode_order);
382 }
383 av_log(avctx, AV_LOG_DEBUG, ".\n");
384
385 if (base_pic->nb_refs[1]) {
386 av_log(avctx, AV_LOG_DEBUG, "L1 refers to");
387 for (i = 0; i < base_pic->nb_refs[1]; i++) {
388 av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
389 base_pic->refs[1][i]->display_order, base_pic->refs[1][i]->encode_order);
390 }
391 av_log(avctx, AV_LOG_DEBUG, ".\n");
392 }
393 }
394
395 av_assert0(!base_pic->encode_issued);
396 for (i = 0; i < base_pic->nb_refs[0]; i++) {
397 av_assert0(base_pic->refs[0][i]);
398 av_assert0(base_pic->refs[0][i]->encode_issued);
399 }
400 for (i = 0; i < base_pic->nb_refs[1]; i++) {
401 av_assert0(base_pic->refs[1][i]);
402 av_assert0(base_pic->refs[1][i]->encode_issued);
403 }
404
405 av_log(avctx, AV_LOG_DEBUG, "Input surface is %p.\n", pic->input_surface->texture);
406
407 pic->recon_surface = (AVD3D12VAFrame *)base_pic->recon_image->data[0];
408 av_log(avctx, AV_LOG_DEBUG, "Recon surface is %p.\n",
409 pic->recon_surface->texture);
410
411 pic->subresource_index = ctx->is_texture_array ? pic->recon_surface->subresource_index : 0;
412
413 pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
414 if (!pic->output_buffer_ref) {
415 err = AVERROR(ENOMEM);
416 goto fail;
417 }
418 pic->output_buffer = (ID3D12Resource *)pic->output_buffer_ref->data;
419 av_log(avctx, AV_LOG_DEBUG, "Output buffer is %p.\n",
420 pic->output_buffer);
421
423 if (err < 0)
424 goto fail;
425
426 // Process ROI side data if present and supported
429 if (sd && base_ctx->roi_allowed) {
430 err = d3d12va_encode_setup_roi(avctx, pic, sd->data, sd->size);
431 if (err < 0)
432 goto fail;
433
434 // Enable delta QP flag in rate control only if supported
435 input_args.SequenceControlDesc.RateControl.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_DELTA_QP;
436 av_log(avctx, AV_LOG_DEBUG, "ROI delta QP map created with %d blocks (region size: %d pixels).\n",
437 pic->qp_map_size, ctx->qp_map_region_size);
438 }
439
440 if (ctx->codec->init_picture_params) {
441 err = ctx->codec->init_picture_params(avctx, base_pic);
442 if (err < 0) {
443 av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
444 "parameters: %d.\n", err);
445 goto fail;
446 }
447 }
448
449 if (base_pic->type == FF_HW_PICTURE_TYPE_IDR) {
450 if (ctx->codec->write_sequence_header) {
451 bit_len = 8 * sizeof(data);
452 err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
453 if (err < 0) {
454 av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
455 "header: %d.\n", err);
456 goto fail;
457 }
458 pic->header_size = (int)bit_len / 8;
459 pic->aligned_header_size = pic->header_size % ctx->req.CompressedBitstreamBufferAccessAlignment ?
460 FFALIGN(pic->header_size, ctx->req.CompressedBitstreamBufferAccessAlignment) :
461 pic->header_size;
462
463 hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&ptr);
464 if (FAILED(hr)) {
465 err = AVERROR_UNKNOWN;
466 goto fail;
467 }
468
469 memcpy(ptr, data, pic->aligned_header_size);
470 ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
471 }
472 }
473
474 d3d12_refs.NumTexture2Ds = base_pic->nb_refs[0] + base_pic->nb_refs[1];
475 if (d3d12_refs.NumTexture2Ds) {
476 d3d12_refs.ppTexture2Ds = av_calloc(d3d12_refs.NumTexture2Ds,
477 sizeof(*d3d12_refs.ppTexture2Ds));
478 if (!d3d12_refs.ppTexture2Ds) {
479 err = AVERROR(ENOMEM);
480 goto fail;
481 }
482
483 if (ctx->is_texture_array) {
484 d3d12_refs.pSubresources = av_calloc(d3d12_refs.NumTexture2Ds,
485 sizeof(*d3d12_refs.pSubresources));
486 if (!d3d12_refs.pSubresources) {
487 err = AVERROR(ENOMEM);
488 goto fail;
489 }
490 }
491
492 i = 0;
493 for (j = 0; j < base_pic->nb_refs[0]; j++) {
494 d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->recon_surface->texture;
495 if (ctx->is_texture_array)
496 d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->subresource_index;
497 i++;
498 }
499 for (j = 0; j < base_pic->nb_refs[1]; j++) {
500 d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->recon_surface->texture;
501 if (ctx->is_texture_array)
502 d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->subresource_index;
503 i++;
504 }
505 }
506
507 input_args.PictureControlDesc.IntraRefreshFrameIndex = ctx->intra_refresh_frame_index;
508 if (base_pic->is_reference)
509 input_args.PictureControlDesc.Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE;
510
511 input_args.PictureControlDesc.PictureControlCodecData = pic->pic_ctl;
512 input_args.PictureControlDesc.ReferenceFrames = d3d12_refs;
513 input_args.CurrentFrameBitstreamMetadataSize = pic->aligned_header_size;
514
515 output_args.Bitstream.pBuffer = pic->output_buffer;
516 output_args.Bitstream.FrameStartOffset = pic->aligned_header_size;
517 output_args.ReconstructedPicture.pReconstructedPicture = pic->recon_surface->texture;
518 output_args.ReconstructedPicture.ReconstructedPictureSubresource = ctx->is_texture_array ? pic->subresource_index : 0;
519 output_args.EncoderOutputMetadata.pBuffer = pic->encoded_metadata;
520 output_args.EncoderOutputMetadata.Offset = 0;
521
522 input_metadata.HWLayoutMetadata.pBuffer = pic->encoded_metadata;
523 input_metadata.HWLayoutMetadata.Offset = 0;
524
525 output_metadata.ResolvedLayoutMetadata.pBuffer = pic->resolved_metadata;
526 output_metadata.ResolvedLayoutMetadata.Offset = 0;
527
528 err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
529 if (err < 0)
530 goto fail;
531
532 hr = ID3D12CommandAllocator_Reset(command_allocator);
533 if (FAILED(hr)) {
534 err = AVERROR_UNKNOWN;
535 goto fail;
536 }
537
538 hr = ID3D12VideoEncodeCommandList2_Reset(cmd_list, command_allocator);
539 if (FAILED(hr)) {
540 err = AVERROR_UNKNOWN;
541 goto fail;
542 }
543
544#define TRANSITION_BARRIER(res, subres, before, after) \
545 (D3D12_RESOURCE_BARRIER) { \
546 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
547 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
548 .Transition = { \
549 .pResource = res, \
550 .Subresource = subres, \
551 .StateBefore = before, \
552 .StateAfter = after, \
553 }, \
554 }
555
556 barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
557 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
558 D3D12_RESOURCE_STATE_COMMON,
559 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
560 barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
561 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
562 D3D12_RESOURCE_STATE_COMMON,
563 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
564 barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
565 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
566 D3D12_RESOURCE_STATE_COMMON,
567 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
568 barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
569 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
570 D3D12_RESOURCE_STATE_COMMON,
571 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
572
573 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
574
575 if (ctx->is_texture_array)
576 barriers_ref = av_calloc(base_ctx->recon_frames->initial_pool_size * ctx->plane_count,
577 sizeof(D3D12_RESOURCE_BARRIER));
578 else
579 barriers_ref = av_calloc(MAX_DPB_SIZE, sizeof(D3D12_RESOURCE_BARRIER));
580
581 if (ctx->is_texture_array) {
582 D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
583 pic->recon_surface->texture->lpVtbl->GetDesc(pic->recon_surface->texture, &references_tex_array_desc);
584
585 for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
586 reference_subresource++) {
587
588 uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
589 uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
590 uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
591
592 for (uint32_t plane_slice = 0; plane_slice < ctx->plane_count; plane_slice++) {
593 uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
594 plane_slice * references_tex_array_desc.MipLevels * array_size;
595 if (reference_subresource == pic->subresource_index) {
596 barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
597 D3D12_RESOURCE_STATE_COMMON,
598 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
599 } else {
600 barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
601 D3D12_RESOURCE_STATE_COMMON,
602 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
603 }
604 }
605 }
606 } else {
607 barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture,
608 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
609 D3D12_RESOURCE_STATE_COMMON,
610 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
611
612 if (d3d12_refs.NumTexture2Ds) {
613 for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
614 barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
615 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
616 D3D12_RESOURCE_STATE_COMMON,
617 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
618 }
619 }
620 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
621
622 ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list, ctx->encoder, ctx->encoder_heap,
623 &input_args, &output_args);
624
625 barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
626 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
627 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
628 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
629
630 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 1, &barriers[3]);
631
632 ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
633
634 if (barriers_ref_index > 0) {
635 for (i = 0; i < barriers_ref_index; i++)
636 FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[i].Transition.StateBefore, barriers_ref[i].Transition.StateAfter);
637
638 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
639 barriers_ref);
640 }
641
642 barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
643 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
644 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
645 D3D12_RESOURCE_STATE_COMMON);
646 barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
647 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
648 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
649 D3D12_RESOURCE_STATE_COMMON);
650 barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
651 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
652 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
653 D3D12_RESOURCE_STATE_COMMON);
654 barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
655 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
656 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
657 D3D12_RESOURCE_STATE_COMMON);
658
659 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
660
661 hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
662 if (FAILED(hr)) {
663 err = AVERROR_UNKNOWN;
664 goto fail;
665 }
666
667 hr = ID3D12CommandQueue_Wait(ctx->command_queue, pic->input_surface->sync_ctx.fence,
669 if (FAILED(hr)) {
670 err = AVERROR_UNKNOWN;
671 goto fail;
672 }
673
674 ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
675
676 hr = ID3D12CommandQueue_Signal(ctx->command_queue, pic->input_surface->sync_ctx.fence,
678 if (FAILED(hr)) {
679 err = AVERROR_UNKNOWN;
680 goto fail;
681 }
682
683 hr = ID3D12CommandQueue_Signal(ctx->command_queue, ctx->sync_ctx.fence, ++ctx->sync_ctx.fence_value);
684 if (FAILED(hr)) {
685 err = AVERROR_UNKNOWN;
686 goto fail;
687 }
688
689 err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
690 if (err < 0)
691 goto fail;
692
693 pic->fence_value = ctx->sync_ctx.fence_value;
694
695 // Update intra refresh frame index for next frame
696 if (ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
697 ctx->intra_refresh_frame_index =
698 (ctx->intra_refresh_frame_index + 1) % ctx->intra_refresh.IntraRefreshDuration;
699 }
700
701 if (d3d12_refs.ppTexture2Ds)
702 av_freep(&d3d12_refs.ppTexture2Ds);
703
704 if (ctx->is_texture_array && d3d12_refs.pSubresources)
705 av_freep(&d3d12_refs.pSubresources);
706
707 if (barriers_ref)
708 av_freep(&barriers_ref);
709
710 return 0;
711
712fail:
713 if (command_allocator)
714 d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
715
716 if (d3d12_refs.ppTexture2Ds)
717 av_freep(&d3d12_refs.ppTexture2Ds);
718
719 if (ctx->is_texture_array && d3d12_refs.pSubresources)
720 av_freep(&d3d12_refs.pSubresources);
721
722 if (barriers_ref)
723 av_freep(&barriers_ref);
724
725 if (ctx->codec->free_picture_params)
726 ctx->codec->free_picture_params(pic);
727
729 pic->output_buffer = NULL;
732 return err;
733}
734
736 FFHWBaseEncodePicture *base_pic)
737{
738 D3D12VAEncodePicture *pic = base_pic->priv;
739
740 d3d12va_encode_wait(avctx, base_pic);
741
742 if (pic->output_buffer_ref) {
743 av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
744 "%"PRId64"/%"PRId64".\n",
745 base_pic->display_order, base_pic->encode_order);
746
748 pic->output_buffer = NULL;
749 }
750
753
754 return 0;
755}
756
758{
760
761 switch (ctx->rc.Mode)
762 {
763 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP:
764 av_freep(&ctx->rc.ConfigParams.pConfiguration_CQP);
765 break;
766 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR:
767 av_freep(&ctx->rc.ConfigParams.pConfiguration_CBR);
768 break;
769 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR:
770 av_freep(&ctx->rc.ConfigParams.pConfiguration_VBR);
771 break;
772 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR:
773 av_freep(&ctx->rc.ConfigParams.pConfiguration_QVBR);
774 break;
775 default:
776 break;
777 }
778
779 return 0;
780}
781
783{
785 D3D12VAEncodePicture *priv = pic->priv;
786 AVFrame *frame = pic->input_image;
787
788 if (ctx->codec->picture_priv_data_size > 0) {
789 pic->codec_priv = av_mallocz(ctx->codec->picture_priv_data_size);
790 if (!pic->codec_priv)
791 return AVERROR(ENOMEM);
792 }
793
794 priv->input_surface = (AVD3D12VAFrame *)frame->data[0];
795
796 return 0;
797}
798
800{
802 D3D12VAEncodePicture *priv = pic->priv;
803
804 if (pic->encode_issued)
805 d3d12va_encode_discard(avctx, pic);
806
807 if (ctx->codec->free_picture_params)
808 ctx->codec->free_picture_params(priv);
809
810 // Free ROI QP map if allocated
811 av_freep(&priv->qp_map);
812
813 return 0;
814}
815
817 D3D12VAEncodePicture *pic, size_t *size)
818{
819 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta = NULL;
820 uint8_t *data;
821 HRESULT hr;
822 int err;
823
824 hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
825 if (FAILED(hr)) {
826 err = AVERROR_UNKNOWN;
827 return err;
828 }
829
830 meta = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)data;
831
832 if (meta->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
833 av_log(avctx, AV_LOG_ERROR, "Encode failed %"PRIu64"\n", meta->EncodeErrorFlags);
834 err = AVERROR(EINVAL);
835 return err;
836 }
837
838 if (meta->EncodedBitstreamWrittenBytesCount == 0) {
839 av_log(avctx, AV_LOG_ERROR, "No bytes were written to encoded bitstream\n");
840 err = AVERROR(EINVAL);
841 return err;
842 }
843
844 *size = meta->EncodedBitstreamWrittenBytesCount;
845
846 ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
847
848 return 0;
849}
850
853{
854 int err;
855 uint8_t *ptr, *mapped_data;
856 size_t total_size = 0;
857 HRESULT hr;
858
859 err = d3d12va_encode_get_buffer_size(avctx, pic, &total_size);
860 if (err < 0)
861 goto end;
862
863 total_size += pic->header_size;
864 av_log(avctx, AV_LOG_DEBUG, "Output buffer size %zu\n", total_size);
865
866 hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&mapped_data);
867 if (FAILED(hr)) {
868 err = AVERROR_UNKNOWN;
869 goto end;
870 }
871
872 err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
873 if (err < 0)
874 goto end;
875 ptr = pkt->data;
876
877 memcpy(ptr, mapped_data, pic->header_size);
878
879 ptr += pic->header_size;
880 mapped_data += pic->aligned_header_size;
881 total_size -= pic->header_size;
882
883 memcpy(ptr, mapped_data, total_size);
884
885 ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
886
887end:
889 pic->output_buffer = NULL;
890 return err;
891}
892
895{
897 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
898 D3D12VAEncodePicture *pic = base_pic->priv;
899 AVPacket *pkt_ptr = pkt;
900 int err = 0;
901
902 err = d3d12va_encode_wait(avctx, base_pic);
903 if (err < 0)
904 return err;
905
906 if (ctx->codec->get_coded_data)
907 err = ctx->codec->get_coded_data(avctx, pic, pkt);
908 else
909 err = d3d12va_encode_get_coded_data(avctx, pic, pkt);
910
911 if (err < 0)
912 return err;
913
914 if (pic->non_independent_frame) {
915 if (pic->tail_size) {
916 if (base_ctx->tail_pkt->size) {
917 err = AVERROR_BUG;
918 goto end;
919 }
920 err = ff_get_encode_buffer(avctx, base_ctx->tail_pkt, pic->tail_size, 0);
921 if (err < 0)
922 goto end;
923 memcpy(base_ctx->tail_pkt->data, pic->tail_data, pic->tail_size);
924 pkt_ptr = base_ctx->tail_pkt;
925 }
926 }
927
928 av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
929 base_pic->display_order, base_pic->encode_order);
930
931 /* FF_HW_FLAG_TIMESTAMP_NO_DELAY: DTS = PTS for codecs whose output is
932 * already in display order (e.g. AV1 with show_existing_frame). */
934 pkt_ptr,
935 ctx->codec->flags & FF_HW_FLAG_TIMESTAMP_NO_DELAY);
936
937end:
938 return err;
939}
940
942{
943 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
947 int i, depth;
948
950 if (!desc) {
951 av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
952 base_ctx->input_frames->sw_format);
953 return AVERROR(EINVAL);
954 }
955
956 depth = desc->comp[0].depth;
957 for (i = 1; i < desc->nb_components; i++) {
958 if (desc->comp[i].depth != depth) {
959 av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
960 desc->name);
961 return AVERROR(EINVAL);
962 }
963 }
964 av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
965 desc->name);
966
967 av_assert0(ctx->codec->profiles);
968 for (i = 0; (ctx->codec->profiles[i].av_profile !=
969 AV_PROFILE_UNKNOWN); i++) {
970 profile = &ctx->codec->profiles[i];
971 if (depth != profile->depth ||
972 desc->nb_components != profile->nb_components)
973 continue;
974 if (desc->nb_components > 1 &&
975 (desc->log2_chroma_w != profile->log2_chroma_w ||
976 desc->log2_chroma_h != profile->log2_chroma_h))
977 continue;
978 if (avctx->profile != profile->av_profile &&
979 avctx->profile != AV_PROFILE_UNKNOWN)
980 continue;
981
982 ctx->profile = profile;
983 break;
984 }
985 if (!ctx->profile) {
986 av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
987 return AVERROR(ENOSYS);
988 }
989
990 avctx->profile = profile->av_profile;
991 return 0;
992}
993
995 // Bitrate Quality
996 // | Maxrate | HRD/VBV
997 { 0 }, // | | | |
998 { RC_MODE_CQP, "CQP", 0, 0, 1, 0, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP },
999 { RC_MODE_CBR, "CBR", 1, 0, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR },
1000 { RC_MODE_VBR, "VBR", 1, 1, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR },
1001 { RC_MODE_QVBR, "QVBR", 1, 1, 1, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR },
1002};
1003
1005{
1006 HRESULT hr;
1008 D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE d3d12_rc_mode = {
1009 .Codec = ctx->codec->d3d12_codec,
1010 };
1011
1012 if (!rc_mode->d3d12_mode)
1013 return 0;
1014
1015 d3d12_rc_mode.IsSupported = 0;
1016 d3d12_rc_mode.RateControlMode = rc_mode->d3d12_mode;
1017
1018 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1019 D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE,
1020 &d3d12_rc_mode, sizeof(d3d12_rc_mode));
1021 if (FAILED(hr)) {
1022 av_log(avctx, AV_LOG_ERROR, "Failed to check rate control support.\n");
1023 return 0;
1024 }
1025
1026 return d3d12_rc_mode.IsSupported;
1027}
1028
1030{
1032 int64_t rc_target_bitrate;
1033 int64_t rc_peak_bitrate;
1034 int rc_quality;
1035 int64_t hrd_buffer_size;
1036 int64_t hrd_initial_buffer_fullness;
1037 int fr_num, fr_den;
1039
1040#define SET_QP_RANGE(ctl) do { \
1041 if (avctx->qmin > 0 || avctx->qmax > 0) { \
1042 ctl->MinQP = avctx->qmin; \
1043 ctl->MaxQP = avctx->qmax; \
1044 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_QP_RANGE; \
1045 } \
1046 } while(0)
1047
1048#define SET_MAX_FRAME_SIZE(ctl) do { \
1049 if (ctx->max_frame_size > 0) { \
1050 ctl->MaxFrameBitSize = ctx->max_frame_size * 8; \
1051 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_MAX_FRAME_SIZE; \
1052 } \
1053 } while(0)
1054
1055 // Rate control mode selection:
1056 // * If the user has set a mode explicitly with the rc_mode option,
1057 // use it and fail if it is not available.
1058 // * If an explicit QP option has been set, use CQP.
1059 // * If the codec is CQ-only, use CQP.
1060 // * If the QSCALE avcodec option is set, use CQP.
1061 // * If bitrate and quality are both set, try QVBR.
1062 // * If quality is set, try CQP.
1063 // * If bitrate and maxrate are set and have the same value, try CBR.
1064 // * If a bitrate is set, try VBR, then CBR.
1065 // * If no bitrate is set, try CQP.
1066
1067#define TRY_RC_MODE(mode, fail) do { \
1068 rc_mode = &d3d12va_encode_rc_modes[mode]; \
1069 if (!(rc_mode->d3d12_mode && check_rate_control_support(avctx, rc_mode))) { \
1070 if (fail) { \
1071 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1072 "RC mode.\n", rc_mode->name); \
1073 return AVERROR(EINVAL); \
1074 } \
1075 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1076 "RC mode.\n", rc_mode->name); \
1077 rc_mode = NULL; \
1078 } else { \
1079 goto rc_mode_found; \
1080 } \
1081 } while (0)
1082
1083 if (ctx->explicit_rc_mode)
1084 TRY_RC_MODE(ctx->explicit_rc_mode, 1);
1085
1086 if (ctx->explicit_qp)
1088
1089 if (ctx->codec->flags & FF_HW_FLAG_CONSTANT_QUALITY_ONLY)
1091
1092 if (avctx->flags & AV_CODEC_FLAG_QSCALE)
1094
1095 if (avctx->bit_rate > 0 && avctx->global_quality > 0)
1097
1098 if (avctx->global_quality > 0) {
1100 }
1101
1102 if (avctx->bit_rate > 0 && avctx->rc_max_rate == avctx->bit_rate)
1104
1105 if (avctx->bit_rate > 0) {
1108 } else {
1110 }
1111
1112 av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1113 "RC mode compatible with selected options.\n");
1114 return AVERROR(EINVAL);
1115
1116rc_mode_found:
1117 if (rc_mode->bitrate) {
1118 if (avctx->bit_rate <= 0) {
1119 av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s "
1120 "RC mode.\n", rc_mode->name);
1121 return AVERROR(EINVAL);
1122 }
1123
1124 if (rc_mode->maxrate) {
1125 if (avctx->rc_max_rate > 0) {
1126 if (avctx->rc_max_rate < avctx->bit_rate) {
1127 av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: "
1128 "bitrate (%"PRId64") must not be greater than "
1129 "maxrate (%"PRId64").\n", avctx->bit_rate,
1130 avctx->rc_max_rate);
1131 return AVERROR(EINVAL);
1132 }
1133 rc_target_bitrate = avctx->bit_rate;
1134 rc_peak_bitrate = avctx->rc_max_rate;
1135 } else {
1136 // We only have a target bitrate, but this mode requires
1137 // that a maximum rate be supplied as well. Since the
1138 // user does not want this to be a constraint, arbitrarily
1139 // pick a maximum rate of double the target rate.
1140 rc_target_bitrate = avctx->bit_rate;
1141 rc_peak_bitrate = 2 * avctx->bit_rate;
1142 }
1143 } else {
1144 if (avctx->rc_max_rate > avctx->bit_rate) {
1145 av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored "
1146 "in %s RC mode.\n", rc_mode->name);
1147 }
1148 rc_target_bitrate = avctx->bit_rate;
1149 rc_peak_bitrate = 0;
1150 }
1151 } else {
1152 rc_target_bitrate = 0;
1153 rc_peak_bitrate = 0;
1154 }
1155
1156 if (rc_mode->quality) {
1157 if (ctx->explicit_qp) {
1158 rc_quality = ctx->explicit_qp;
1159 } else if (avctx->global_quality > 0) {
1160 if (avctx->flags & AV_CODEC_FLAG_QSCALE)
1161 rc_quality = avctx->global_quality / FF_QP2LAMBDA;
1162 else
1163 rc_quality = avctx->global_quality;
1164 } else {
1165 rc_quality = ctx->codec->default_quality;
1166 av_log(avctx, AV_LOG_WARNING, "No quality level set; "
1167 "using default (%d).\n", rc_quality);
1168 }
1169 } else {
1170 rc_quality = 0;
1171 }
1172
1173 if (rc_mode->hrd) {
1174 if (avctx->rc_buffer_size)
1175 hrd_buffer_size = avctx->rc_buffer_size;
1176 else if (avctx->rc_max_rate > 0)
1177 hrd_buffer_size = avctx->rc_max_rate;
1178 else
1179 hrd_buffer_size = avctx->bit_rate;
1180 if (avctx->rc_initial_buffer_occupancy) {
1181 if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1182 av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1183 "must have initial buffer size (%d) <= "
1184 "buffer size (%"PRId64").\n",
1185 avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1186 return AVERROR(EINVAL);
1187 }
1188 hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1189 } else {
1190 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1191 }
1192 } else {
1193 if (avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
1194 av_log(avctx, AV_LOG_WARNING, "Buffering settings are ignored "
1195 "in %s RC mode.\n", rc_mode->name);
1196 }
1197
1198 hrd_buffer_size = 0;
1199 hrd_initial_buffer_fullness = 0;
1200 }
1201
1202 if (rc_target_bitrate > UINT32_MAX ||
1203 hrd_buffer_size > UINT32_MAX ||
1204 hrd_initial_buffer_fullness > UINT32_MAX) {
1205 av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1206 "greater are not supported by D3D12.\n");
1207 return AVERROR(EINVAL);
1208 }
1209
1210 ctx->rc_quality = rc_quality;
1211
1212 av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s.\n", rc_mode->name);
1213
1214 if (rc_mode->quality)
1215 av_log(avctx, AV_LOG_VERBOSE, "RC quality: %d.\n", rc_quality);
1216
1217 if (rc_mode->hrd) {
1218 av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1219 "initial fullness %"PRId64" bits.\n",
1220 hrd_buffer_size, hrd_initial_buffer_fullness);
1221 }
1222
1223 if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1224 av_reduce(&fr_num, &fr_den,
1225 avctx->framerate.num, avctx->framerate.den, 65535);
1226 else
1227 av_reduce(&fr_num, &fr_den,
1228 avctx->time_base.den, avctx->time_base.num, 65535);
1229
1230 av_log(avctx, AV_LOG_VERBOSE, "RC framerate: %d/%d (%.2f fps).\n",
1231 fr_num, fr_den, (double)fr_num / fr_den);
1232
1233 ctx->rc.Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
1234 ctx->rc.TargetFrameRate.Numerator = fr_num;
1235 ctx->rc.TargetFrameRate.Denominator = fr_den;
1236 ctx->rc.Mode = rc_mode->d3d12_mode;
1237
1238 switch (rc_mode->mode) {
1239 case RC_MODE_CQP:
1240 // cqp ConfigParams will be updated in ctx->codec->configure.
1241 break;
1242 case RC_MODE_CBR: {
1243 D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR *cbr_ctl;
1244
1245 ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR);
1246 cbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1247 if (!cbr_ctl)
1248 return AVERROR(ENOMEM);
1249
1250 cbr_ctl->TargetBitRate = rc_target_bitrate;
1251 cbr_ctl->VBVCapacity = hrd_buffer_size;
1252 cbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1253 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1254
1255 SET_QP_RANGE(cbr_ctl);
1256 SET_MAX_FRAME_SIZE(cbr_ctl);
1257
1258 ctx->rc.ConfigParams.pConfiguration_CBR = cbr_ctl;
1259 break;
1260 }
1261 case RC_MODE_VBR: {
1262 D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR *vbr_ctl;
1263
1264 ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR);
1265 vbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1266 if (!vbr_ctl)
1267 return AVERROR(ENOMEM);
1268
1269 vbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1270 vbr_ctl->PeakBitRate = rc_peak_bitrate;
1271 vbr_ctl->VBVCapacity = hrd_buffer_size;
1272 vbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1273 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1274
1275 SET_QP_RANGE(vbr_ctl);
1276 SET_MAX_FRAME_SIZE(vbr_ctl);
1277
1278 ctx->rc.ConfigParams.pConfiguration_VBR = vbr_ctl;
1279 break;
1280 }
1281 case RC_MODE_QVBR: {
1282 D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR *qvbr_ctl;
1283
1284 ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR);
1285 qvbr_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1286 if (!qvbr_ctl)
1287 return AVERROR(ENOMEM);
1288
1289 qvbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1290 qvbr_ctl->PeakBitRate = rc_peak_bitrate;
1291 qvbr_ctl->ConstantQualityTarget = rc_quality;
1292
1293 SET_QP_RANGE(qvbr_ctl);
1294 SET_MAX_FRAME_SIZE(qvbr_ctl);
1295
1296 ctx->rc.ConfigParams.pConfiguration_QVBR = qvbr_ctl;
1297 break;
1298 }
1299 default:
1300 break;
1301 }
1302 return 0;
1303}
1304
1306{
1307 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1309 uint32_t ref_l0, ref_l1;
1310 int err;
1311 HRESULT hr;
1312 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT support;
1313 union {
1314 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
1315 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
1316#if CONFIG_AV1_D3D12VA_ENCODER
1317 D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
1318#endif
1319 } codec_support;
1320
1321 support.NodeIndex = 0;
1322 support.Codec = ctx->codec->d3d12_codec;
1323 support.Profile = ctx->profile->d3d12_profile;
1324
1325 switch (ctx->codec->d3d12_codec) {
1326 case D3D12_VIDEO_ENCODER_CODEC_H264:
1327 support.PictureSupport.DataSize = sizeof(codec_support.h264);
1328 support.PictureSupport.pH264Support = &codec_support.h264;
1329 break;
1330
1331 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1332 support.PictureSupport.DataSize = sizeof(codec_support.hevc);
1333 support.PictureSupport.pHEVCSupport = &codec_support.hevc;
1334 break;
1335
1336#if CONFIG_AV1_D3D12VA_ENCODER
1337 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1338 memset(&codec_support.av1, 0, sizeof(codec_support.av1));
1339 codec_support.av1.PredictionMode = D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_SINGLE_REFERENCE;
1340 support.PictureSupport.DataSize = sizeof(codec_support.av1);
1341 support.PictureSupport.pAV1Support = &codec_support.av1;
1342 break;
1343#endif
1344 default:
1345 av_assert0(0);
1346 }
1347
1348 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1349 &support, sizeof(support));
1350 if (FAILED(hr))
1351 return AVERROR(EINVAL);
1352
1353 if (support.IsSupported) {
1354 switch (ctx->codec->d3d12_codec) {
1355 case D3D12_VIDEO_ENCODER_CODEC_H264:
1356 ref_l0 = FFMIN(support.PictureSupport.pH264Support->MaxL0ReferencesForP,
1357 support.PictureSupport.pH264Support->MaxL1ReferencesForB ?
1358 support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX);
1359 ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB;
1360 break;
1361
1362 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1363 ref_l0 = FFMIN(support.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
1364 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB ?
1365 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX);
1366 ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
1367 break;
1368
1369#if CONFIG_AV1_D3D12VA_ENCODER
1370 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1371 ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
1372 memset(&codec_support.av1, 0, sizeof(codec_support.av1));
1373 codec_support.av1.PredictionMode = D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_COMPOUND_REFERENCE;
1374 support.PictureSupport.DataSize = sizeof(codec_support.av1);
1375 support.PictureSupport.pAV1Support = &codec_support.av1;
1376
1377 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1378 D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1379 &support, sizeof(support));
1380 if (FAILED(hr))
1381 return AVERROR(EINVAL);
1382
1383 ref_l1 = support.IsSupported ? 1 : 0;
1384 break;
1385#endif
1386 default:
1387 av_assert0(0);
1388 }
1389 } else {
1390 ref_l0 = ref_l1 = 0;
1391 }
1392
1393 if (ref_l0 > 0 && ref_l1 > 0 && ctx->bi_not_empty) {
1394 base_ctx->p_to_gpb = 1;
1395 av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, "
1396 "replacing them with B-frames.\n");
1397 }
1398
1399 err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1, ctx->codec->flags, 0);
1400 if (err < 0)
1401 return err;
1402
1403 return 0;
1404}
1405
1407{
1408 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1410
1411 if (ctx->intra_refresh.Mode == D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE)
1412 return 0;
1413
1414 // Check for SDK API availability
1415#if CONFIG_D3D12_INTRA_REFRESH
1416 HRESULT hr;
1417 D3D12_VIDEO_ENCODER_LEVEL_SETTING level = { 0 };
1418 D3D12_VIDEO_ENCODER_LEVELS_H264 h264_level = { 0 };
1419 D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevc_level = { 0 };
1420#if CONFIG_AV1_D3D12VA_ENCODER
1421 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1_level = { 0 };
1422#endif
1423
1424 switch (ctx->codec->d3d12_codec) {
1425 case D3D12_VIDEO_ENCODER_CODEC_H264:
1426 level.DataSize = sizeof(D3D12_VIDEO_ENCODER_LEVELS_H264);
1427 level.pH264LevelSetting = &h264_level;
1428 break;
1429 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1430 level.DataSize = sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
1431 level.pHEVCLevelSetting = &hevc_level;
1432 break;
1433#if CONFIG_AV1_D3D12VA_ENCODER
1434 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1435 level.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1436 level.pAV1LevelSetting = &av1_level;
1437 break;
1438#endif
1439 default:
1440 av_assert0(0);
1441 }
1442
1443 D3D12_FEATURE_DATA_VIDEO_ENCODER_INTRA_REFRESH_MODE intra_refresh_support = {
1444 .NodeIndex = 0,
1445 .Codec = ctx->codec->d3d12_codec,
1446 .Profile = ctx->profile->d3d12_profile,
1447 .Level = level,
1448 .IntraRefreshMode = ctx->intra_refresh.Mode,
1449 };
1450
1451 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1452 D3D12_FEATURE_VIDEO_ENCODER_INTRA_REFRESH_MODE,
1453 &intra_refresh_support, sizeof(intra_refresh_support));
1454
1455 if (FAILED(hr) || !intra_refresh_support.IsSupported) {
1456 av_log(avctx, AV_LOG_ERROR, "Requested intra refresh mode not supported by driver.\n");
1457 return AVERROR(ENOTSUP);
1458 }
1459#else
1460 // Older SDK - validation will occur in init_sequence_params via D3D12_FEATURE_VIDEO_ENCODER_SUPPORT
1461 av_log(avctx, AV_LOG_VERBOSE, "Intra refresh explicit check not available in this SDK.\n"
1462 "Support will be validated during encoder initialization.\n");
1463#endif
1464
1465 // Set duration: use GOP size if not specified
1466 if (ctx->intra_refresh.IntraRefreshDuration == 0) {
1467 ctx->intra_refresh.IntraRefreshDuration = base_ctx->gop_size;
1468 av_log(avctx, AV_LOG_VERBOSE, "Intra refresh duration set to GOP size: %d\n",
1469 ctx->intra_refresh.IntraRefreshDuration);
1470 }
1471
1472 // Initialize frame index
1473 ctx->intra_refresh_frame_index = 0;
1474
1475 av_log(avctx, AV_LOG_VERBOSE, "Intra refresh: mode=%d, duration=%d frames\n",
1476 ctx->intra_refresh.Mode, ctx->intra_refresh.IntraRefreshDuration);
1477
1478 return 0;
1479}
1480
1482{
1483 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1485 AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
1486 HRESULT hr;
1487
1488 D3D12_VIDEO_ENCODER_DESC desc = {
1489 .NodeMask = 0,
1490 .Flags = D3D12_VIDEO_ENCODER_FLAG_NONE,
1491 .EncodeCodec = ctx->codec->d3d12_codec,
1492 .EncodeProfile = ctx->profile->d3d12_profile,
1493 .InputFormat = frames_hwctx->format,
1494 .CodecConfiguration = ctx->codec_conf,
1495 .MaxMotionEstimationPrecision = ctx->me_precision,
1496 };
1497
1498 hr = ID3D12VideoDevice3_CreateVideoEncoder(ctx->video_device3, &desc, &IID_ID3D12VideoEncoder,
1499 (void **)&ctx->encoder);
1500 if (FAILED(hr)) {
1501 av_log(avctx, AV_LOG_ERROR, "Failed to create encoder.\n");
1502 return AVERROR(EINVAL);
1503 }
1504
1505 return 0;
1506}
1507
1509{
1511 HRESULT hr;
1512
1513 D3D12_VIDEO_ENCODER_HEAP_DESC desc = {
1514 .NodeMask = 0,
1515 .Flags = D3D12_VIDEO_ENCODER_HEAP_FLAG_NONE,
1516 .EncodeCodec = ctx->codec->d3d12_codec,
1517 .EncodeProfile = ctx->profile->d3d12_profile,
1518 .EncodeLevel = ctx->level,
1519 .ResolutionsListCount = 1,
1520 .pResolutionList = &ctx->resolution,
1521 };
1522
1523 hr = ID3D12VideoDevice3_CreateVideoEncoderHeap(ctx->video_device3, &desc,
1524 &IID_ID3D12VideoEncoderHeap, (void **)&ctx->encoder_heap);
1525 if (FAILED(hr)) {
1526 av_log(avctx, AV_LOG_ERROR, "Failed to create encoder heap.\n");
1527 return AVERROR(EINVAL);
1528 }
1529
1530 return 0;
1531}
1532
1533static void d3d12va_encode_free_buffer(void *opaque, uint8_t *data)
1534{
1535 ID3D12Resource *pResource;
1536
1537 pResource = (ID3D12Resource *)data;
1538 D3D12_OBJECT_RELEASE(pResource);
1539}
1540
1542{
1543 AVCodecContext *avctx = opaque;
1544 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1546 ID3D12Resource *pResource = NULL;
1547 HRESULT hr;
1549 D3D12_HEAP_PROPERTIES heap_props;
1550 D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_READBACK;
1551
1552 D3D12_RESOURCE_DESC desc = {
1553 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1554 .Alignment = 0,
1555 .Width = FFALIGN(3 * base_ctx->surface_width * base_ctx->surface_height + (1 << 16),
1556 D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT),
1557 .Height = 1,
1558 .DepthOrArraySize = 1,
1559 .MipLevels = 1,
1560 .Format = DXGI_FORMAT_UNKNOWN,
1561 .SampleDesc = { .Count = 1, .Quality = 0 },
1562 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1563 .Flags = D3D12_RESOURCE_FLAG_NONE,
1564 };
1565
1566 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(ctx->hwctx->device, &heap_props, 0, heap_type);
1567
1568 hr = ID3D12Device_CreateCommittedResource(ctx->hwctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
1569 &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource,
1570 (void **)&pResource);
1571
1572 if (FAILED(hr)) {
1573 av_log(avctx, AV_LOG_ERROR, "Failed to create d3d12 buffer.\n");
1574 return NULL;
1575 }
1576
1577 ref = av_buffer_create((uint8_t *)(uintptr_t)pResource,
1578 sizeof(pResource),
1581 if (!ref) {
1582 D3D12_OBJECT_RELEASE(pResource);
1583 return NULL;
1584 }
1585
1586 return ref;
1587}
1588
1590{
1591 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1593 AVD3D12VAFramesContext *frames_ctx = base_ctx->input_frames->hwctx;
1594 HRESULT hr;
1595
1596 ctx->req.NodeIndex = 0;
1597 ctx->req.Codec = ctx->codec->d3d12_codec;
1598 ctx->req.Profile = ctx->profile->d3d12_profile;
1599 ctx->req.InputFormat = frames_ctx->format;
1600 ctx->req.PictureTargetResolution = ctx->resolution;
1601
1602 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3,
1603 D3D12_FEATURE_VIDEO_ENCODER_RESOURCE_REQUIREMENTS,
1604 &ctx->req, sizeof(ctx->req));
1605 if (FAILED(hr)) {
1606 av_log(avctx, AV_LOG_ERROR, "Failed to check encoder resource requirements support.\n");
1607 return AVERROR(EINVAL);
1608 }
1609
1610 if (!ctx->req.IsSupported) {
1611 av_log(avctx, AV_LOG_ERROR, "Encoder resource requirements unsupported.\n");
1612 return AVERROR(EINVAL);
1613 }
1614
1615 ctx->output_buffer_pool = av_buffer_pool_init2(sizeof(ID3D12Resource *), avctx,
1617 if (!ctx->output_buffer_pool)
1618 return AVERROR(ENOMEM);
1619
1620 return 0;
1621}
1622
1624{
1626 ID3D12CommandAllocator *command_allocator = NULL;
1627 int err = AVERROR_UNKNOWN;
1628 HRESULT hr;
1629
1630 D3D12_COMMAND_QUEUE_DESC queue_desc = {
1631 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
1632 .Priority = 0,
1633 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
1634 .NodeMask = 0,
1635 };
1636
1639 if (!ctx->allocator_queue)
1640 return AVERROR(ENOMEM);
1641
1642 hr = ID3D12Device_CreateFence(ctx->hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
1643 &IID_ID3D12Fence, (void **)&ctx->sync_ctx.fence);
1644 if (FAILED(hr)) {
1645 av_log(avctx, AV_LOG_ERROR, "Failed to create fence(%lx)\n", (long)hr);
1646 err = AVERROR_UNKNOWN;
1647 goto fail;
1648 }
1649
1650 ctx->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
1651 if (!ctx->sync_ctx.event)
1652 goto fail;
1653
1654 err = d3d12va_get_valid_command_allocator(avctx, &command_allocator);
1655 if (err < 0)
1656 goto fail;
1657
1658 hr = ID3D12Device_CreateCommandQueue(ctx->hwctx->device, &queue_desc,
1659 &IID_ID3D12CommandQueue, (void **)&ctx->command_queue);
1660 if (FAILED(hr)) {
1661 av_log(avctx, AV_LOG_ERROR, "Failed to create command queue(%lx)\n", (long)hr);
1662 err = AVERROR_UNKNOWN;
1663 goto fail;
1664 }
1665
1666 hr = ID3D12Device_CreateCommandList(ctx->hwctx->device, 0, queue_desc.Type,
1667 command_allocator, NULL, &IID_ID3D12CommandList,
1668 (void **)&ctx->command_list);
1669 if (FAILED(hr)) {
1670 av_log(avctx, AV_LOG_ERROR, "Failed to create command list(%lx)\n", (long)hr);
1671 err = AVERROR_UNKNOWN;
1672 goto fail;
1673 }
1674
1675 hr = ID3D12VideoEncodeCommandList2_Close(ctx->command_list);
1676 if (FAILED(hr)) {
1677 av_log(avctx, AV_LOG_ERROR, "Failed to close the command list(%lx)\n", (long)hr);
1678 err = AVERROR_UNKNOWN;
1679 goto fail;
1680 }
1681
1682 ID3D12CommandQueue_ExecuteCommandLists(ctx->command_queue, 1, (ID3D12CommandList **)&ctx->command_list);
1683
1684 err = d3d12va_sync_with_gpu(avctx);
1685 if (err < 0)
1686 goto fail;
1687
1688 err = d3d12va_discard_command_allocator(avctx, command_allocator, ctx->sync_ctx.fence_value);
1689 if (err < 0)
1690 goto fail;
1691
1692 return 0;
1693
1694fail:
1695 D3D12_OBJECT_RELEASE(command_allocator);
1696 return err;
1697}
1698
1700{
1701 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1704 enum AVPixelFormat recon_format;
1705 int err;
1706
1707 err = ff_hw_base_get_recon_format(base_ctx, NULL, &recon_format);
1708 if (err < 0)
1709 return err;
1710
1711 base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref);
1712 if (!base_ctx->recon_frames_ref)
1713 return AVERROR(ENOMEM);
1714
1715 base_ctx->recon_frames = (AVHWFramesContext *)base_ctx->recon_frames_ref->data;
1716 hwctx = (AVD3D12VAFramesContext *)base_ctx->recon_frames->hwctx;
1717
1719 base_ctx->recon_frames->sw_format = recon_format;
1720 base_ctx->recon_frames->width = base_ctx->surface_width;
1721 base_ctx->recon_frames->height = base_ctx->surface_height;
1722
1723 hwctx->resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
1724 D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1725 if (ctx->is_texture_array) {
1728 }
1729
1730 err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
1731 if (err < 0) {
1732 av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
1733 "frame context: %d.\n", err);
1734 return err;
1735 }
1736
1737 return 0;
1738}
1739
1741 .priv_size = sizeof(D3D12VAEncodePicture),
1742
1744
1745 .issue = &d3d12va_encode_issue,
1746
1747 .output = &d3d12va_encode_output,
1748
1749 .free = &d3d12va_encode_free,
1750};
1751
1756
1758{
1759 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1761 D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
1762 D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
1763 int err;
1764 HRESULT hr;
1765
1766 err = ff_hw_base_encode_init(avctx, base_ctx);
1767 if (err < 0)
1768 goto fail;
1769
1770 base_ctx->op = &d3d12va_type;
1771
1772 ctx->hwctx = base_ctx->device->hwctx;
1773
1774 ctx->resolution.Width = base_ctx->input_frames->width;
1775 ctx->resolution.Height = base_ctx->input_frames->height;
1776
1777 hr = ID3D12Device_QueryInterface(ctx->hwctx->device, &IID_ID3D12Device3, (void **)&ctx->device3);
1778 if (FAILED(hr)) {
1779 av_log(avctx, AV_LOG_ERROR, "ID3D12Device3 interface is not supported.\n");
1780 err = AVERROR_UNKNOWN;
1781 goto fail;
1782 }
1783
1784 hr = ID3D12Device3_QueryInterface(ctx->device3, &IID_ID3D12VideoDevice3, (void **)&ctx->video_device3);
1785 if (FAILED(hr)) {
1786 av_log(avctx, AV_LOG_ERROR, "ID3D12VideoDevice3 interface is not supported.\n");
1787 err = AVERROR_UNKNOWN;
1788 goto fail;
1789 }
1790
1791 if (FAILED(ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1792 &support, sizeof(support))) && !support.VideoEncodeSupport) {
1793 av_log(avctx, AV_LOG_ERROR, "D3D12 video device has no video encoder support.\n");
1794 err = AVERROR(EINVAL);
1795 goto fail;
1796 }
1797
1798 format_info.Format = ((AVD3D12VAFramesContext *)base_ctx->input_frames->hwctx)->format;
1799 if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
1800 &format_info, sizeof(format_info)))) {
1801 av_log(avctx, AV_LOG_ERROR, "Failed to query format plane count: %#lx\n", hr);
1802 err = AVERROR_EXTERNAL;
1803 goto fail;
1804 }
1805 ctx->plane_count = format_info.PlaneCount;
1806
1807 err = d3d12va_encode_set_profile(avctx);
1808 if (err < 0)
1809 goto fail;
1810
1812 if (err < 0)
1813 goto fail;
1814
1815 if (ctx->codec->get_encoder_caps) {
1816 err = ctx->codec->get_encoder_caps(avctx);
1817 if (err < 0)
1818 goto fail;
1819 }
1820
1821 if (ctx->codec->set_tile) {
1822 err = ctx->codec->set_tile(avctx);
1823 if (err < 0)
1824 goto fail;
1825 }
1826
1828 if (err < 0)
1829 goto fail;
1830
1832 if (err < 0)
1833 goto fail;
1834
1835 if (!(ctx->codec->flags & FF_HW_FLAG_SLICE_CONTROL) && avctx->slices > 0) {
1836 av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested "
1837 "but this codec does not support controlling slices.\n");
1838 }
1839
1841 if (err < 0)
1842 goto fail;
1843
1845 if (err < 0)
1846 goto fail;
1847
1848 if (ctx->codec->configure) {
1849 err = ctx->codec->configure(avctx);
1850 if (err < 0)
1851 goto fail;
1852 }
1853
1854 if (ctx->codec->init_sequence_params) {
1855 err = ctx->codec->init_sequence_params(avctx);
1856 if (err < 0) {
1857 av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
1858 "failed: %d.\n", err);
1859 goto fail;
1860 }
1861 }
1862
1863 if (ctx->codec->set_level) {
1864 err = ctx->codec->set_level(avctx);
1865 if (err < 0)
1866 goto fail;
1867 }
1868
1870 if (err < 0)
1871 goto fail;
1872
1873 base_ctx->output_delay = base_ctx->b_per_p;
1874 base_ctx->decode_delay = base_ctx->max_b_depth;
1875
1876 err = d3d12va_create_encoder(avctx);
1877 if (err < 0)
1878 goto fail;
1879
1880 err = d3d12va_create_encoder_heap(avctx);
1881 if (err < 0)
1882 goto fail;
1883
1884 base_ctx->async_encode = 1;
1885 base_ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth,
1886 sizeof(D3D12VAEncodePicture *), 0);
1887 if (!base_ctx->encode_fifo)
1888 return AVERROR(ENOMEM);
1889
1890 if (ctx->codec->write_sequence_header &&
1892 char header_data[MAX_PARAM_BUFFER_SIZE];
1893 size_t header_bit_len = 8 * sizeof(header_data);
1894
1895 err = ctx->codec->write_sequence_header(avctx, header_data, &header_bit_len);
1896 if (err < 0) {
1897 av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
1898 "for global header: %d.\n", err);
1899 goto fail;
1900 }
1901 avctx->extradata_size = (int)((header_bit_len + 7) / 8);
1902 avctx->extradata = av_mallocz(avctx->extradata_size +
1904 if (!avctx->extradata) {
1905 err = AVERROR(ENOMEM);
1906 goto fail;
1907 }
1908 memcpy(avctx->extradata, header_data, avctx->extradata_size);
1909 }
1910
1911 return 0;
1912
1913fail:
1914 return err;
1915}
1916
1918{
1919 int num_allocator = 0;
1920 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1922 FFHWBaseEncodePicture *pic, *next;
1923 CommandAllocator allocator;
1924
1925 if (!base_ctx->frame)
1926 return 0;
1927
1928 for (pic = base_ctx->pic_start; pic; pic = next) {
1929 next = pic->next;
1930 d3d12va_encode_free(avctx, pic);
1931 }
1932
1934
1935 av_buffer_pool_uninit(&ctx->output_buffer_pool);
1936
1937 D3D12_OBJECT_RELEASE(ctx->command_list);
1938 D3D12_OBJECT_RELEASE(ctx->command_queue);
1939
1940 if (ctx->allocator_queue) {
1941 while (av_fifo_read(ctx->allocator_queue, &allocator, 1) >= 0) {
1942 num_allocator++;
1944 }
1945
1946 av_log(avctx, AV_LOG_VERBOSE, "Total number of command allocators reused: %d\n", num_allocator);
1947 }
1948
1949 av_fifo_freep2(&ctx->allocator_queue);
1950
1951 D3D12_OBJECT_RELEASE(ctx->sync_ctx.fence);
1952 if (ctx->sync_ctx.event)
1953 CloseHandle(ctx->sync_ctx.event);
1954
1955 D3D12_OBJECT_RELEASE(ctx->encoder_heap);
1956 D3D12_OBJECT_RELEASE(ctx->encoder);
1957 D3D12_OBJECT_RELEASE(ctx->video_device3);
1958 D3D12_OBJECT_RELEASE(ctx->device3);
1959
1960 ff_hw_base_encode_close(base_ctx);
1961
1962 return 0;
1963}
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define av_clip_int8
Definition common.h:109
#define av_clip_int16
Definition common.h:115
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static int d3d12va_encode_free(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
#define TRY_RC_MODE(mode, fail)
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static int d3d12va_discard_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator *pAllocator, uint64_t fence_value)
static int d3d12va_encode_prepare_output_buffers(AVCodecContext *avctx)
static const D3D12VAEncodeRCMode d3d12va_encode_rc_modes[]
static int d3d12va_fence_completion(AVD3D12VASyncContext *psync_ctx)
static int d3d12va_sync_with_gpu(AVCodecContext *avctx)
static int d3d12va_encode_issue(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
static int d3d12va_encode_free_rc_params(AVCodecContext *avctx)
static void d3d12va_encode_free_buffer(void *opaque, uint8_t *data)
static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
static int d3d12va_encode_init_rate_control(AVCodecContext *avctx)
static int d3d12va_get_valid_command_allocator(AVCodecContext *avctx, ID3D12CommandAllocator **ppAllocator)
void ff_d3d12va_encode_check_encoder_feature_flags(void *log_ctx, D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags)
#define TRANSITION_BARRIER(res, subres, before, after)
const AVCodecHWConfigInternal *const ff_d3d12va_encode_hw_configs[]
static int d3d12va_encode_wait(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
static int check_rate_control_support(AVCodecContext *avctx, const D3D12VAEncodeRCMode *rc_mode)
static const FFHWEncodePictureOperation d3d12va_type
#define SET_MAX_FRAME_SIZE(ctl)
static int d3d12va_encode_discard(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic)
#define SET_QP_RANGE(ctl)
static int d3d12va_create_encoder_heap(AVCodecContext *avctx)
static int d3d12va_encode_get_coded_data(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AVPacket *pkt)
int ff_d3d12va_encode_init(AVCodecContext *avctx)
static int d3d12va_encode_setup_roi(AVCodecContext *avctx, D3D12VAEncodePicture *pic, const uint8_t *data, size_t size)
static int d3d12va_encode_get_buffer_size(AVCodecContext *avctx, D3D12VAEncodePicture *pic, size_t *size)
int ff_d3d12va_encode_close(AVCodecContext *avctx)
static int d3d12va_encode_output(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
static int d3d12va_encode_set_profile(AVCodecContext *avctx)
static int d3d12va_encode_create_metadata_buffers(AVCodecContext *avctx, D3D12VAEncodePicture *pic)
static int d3d12va_encode_init(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx)
static int d3d12va_create_encoder(AVCodecContext *avctx)
static AVBufferRef * d3d12va_encode_alloc_output_buffer(void *opaque, size_t size)
static int d3d12va_encode_init_intra_refresh(AVCodecContext *avctx)
static int d3d12va_encode_create_command_objects(AVCodecContext *avctx)
#define D3D12VA_VIDEO_ENC_ASYNC_DEPTH
@ RC_MODE_CQP
@ RC_MODE_QVBR
@ RC_MODE_CBR
@ RC_MODE_VBR
#define MAX_PARAM_BUFFER_SIZE
#define AV_PROFILE_UNKNOWN
Definition defs.h:65
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
#define fail
Definition test.h:479
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition avcodec.h:213
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition avcodec.h:318
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
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
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition buffer.h:114
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
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition buffer.c:328
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition buffer.c:390
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
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition avutil.h:226
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
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
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
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
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition frame.c:659
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
@ AV_FRAME_DATA_REGIONS_OF_INTEREST
Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of array element is ...
Definition frame.h:165
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
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
int ff_hw_base_encode_receive_packet(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, AVPacket *pkt)
int ff_hw_base_encode_set_output_property(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx, FFHWBaseEncodePicture *pic, AVPacket *pkt, int flag_no_delay)
int ff_hw_base_encode_init(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx)
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)
int ff_hw_base_get_recon_format(FFHWBaseEncodeContext *ctx, const void *hwconfig, enum AVPixelFormat *fmt)
int ff_hw_base_encode_close(FFHWBaseEncodeContext *ctx)
#define MAX_DPB_SIZE
@ FF_HW_FLAG_SLICE_CONTROL
@ FF_HW_FLAG_CONSTANT_QUALITY_ONLY
@ FF_HW_FLAG_TIMESTAMP_NO_DELAY
@ FF_HW_PICTURE_TYPE_IDR
static const char * ff_hw_base_encode_get_pictype_name(const int type)
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
An API-specific header for AV_HWDEVICE_TYPE_D3D12VA.
@ AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY
Indicates that frame data should be allocated using a texture array resource.
#define D3D12_OBJECT_RELEASE(pInterface)
A release macro used by D3D12 objects highly frequently.
#define DX_CHECK(hr)
A check macro used by D3D12 functions highly frequently.
common internal API header
const char * desc
Definition libsvtav1.c:83
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFMIN(a, b)
Definition macros.h:49
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
const char data[16]
Definition mxf.c:149
int profile
Definition mxfenc.c:2299
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition pixfmt.h:440
mfxU16 rc_mode
Definition qsvenc.c:141
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
int rc_buffer_size
decoder bitstream buffer size
Definition avcodec.h:1273
int global_quality
Global quality for codecs which cannot change it per frame.
Definition avcodec.h:1235
AVRational framerate
Definition avcodec.h:563
int64_t bit_rate
the average bitrate
Definition avcodec.h:493
int rc_initial_buffer_occupancy
Number of bits which should be loaded into the rc buffer before decoding starts.
Definition avcodec.h:1316
int profile
profile
Definition avcodec.h:1637
int64_t rc_max_rate
maximum bitrate
Definition avcodec.h:1288
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avcodec.h:547
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
int extradata_size
Definition avcodec.h:527
void * priv_data
Definition avcodec.h:470
int slices
Number of slices.
Definition avcodec.h:1037
D3D12VA frame descriptor for pool allocation.
ID3D12Resource * texture
The texture in which the frame is located.
AVD3D12VASyncContext sync_ctx
The sync context for the texture.
int subresource_index
Index of the subresource within the texture.
This struct is allocated as AVHWFramesContext.hwctx.
D3D12_RESOURCE_FLAGS resource_flags
Options for working with resources.
AVD3D12VAFrameFlags flags
A combination of AVD3D12VAFrameFlags.
DXGI_FORMAT format
DXGI_FORMAT format.
This struct is used to sync d3d12 execution.
HANDLE event
A handle to the event object that's raised when the fence reaches a certain value.
ID3D12Fence * fence
D3D12 fence object.
uint64_t fence_value
The fence value used for sync.
Structure to hold side data for an AVFrame.
Definition frame.h:327
size_t size
Definition frame.h:330
uint8_t * data
Definition frame.h:329
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int initial_pool_size
Initial size of the frame pool.
Definition hwcontext.h:190
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Structure describing a single Region Of Interest.
Definition frame.h:398
uint32_t self_size
Must be set to the size of this data structure (that is, sizeof(AVRegionOfInterest)).
Definition frame.h:403
AVRational qoffset
Quantisation offset.
Definition frame.h:440
int top
Distance in pixels from the top edge of the frame to the top and bottom edges and from the left edge ...
Definition frame.h:413
ID3D12CommandAllocator * command_allocator
AVBufferRef * output_buffer_ref
ID3D12Resource * encoded_metadata
char tail_data[MAX_PARAM_BUFFER_SIZE]
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl
ID3D12Resource * resolved_metadata
AVD3D12VAFrame * recon_surface
AVD3D12VAFrame * input_surface
ID3D12Resource * output_buffer
AVBufferRef * recon_frames_ref
AVHWFramesContext * input_frames
AVHWDeviceContext * device
const struct FFHWEncodePictureOperation * op
AVPacket * tail_pkt
Tail data of a pic, now only used for av1 repeat frame header.
FFHWBaseEncodePicture * pic_start
AVHWFramesContext * recon_frames
struct FFHWBaseEncodePicture * next
int nb_refs[MAX_REFERENCE_LIST_NUM]
struct FFHWBaseEncodePicture * refs[MAX_REFERENCE_LIST_NUM][MAX_PICTURE_REFERENCES]
uint8_t level
Definition svq3.c:208
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static int ref[MAX_W *MAX_W]
#define width
Definition dsp.h:89
int size