FFmpeg
Loading...
Searching...
No Matches
d3d12va_encode_av1.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/opt.h"
25#include "libavutil/common.h"
26#include "libavutil/mem.h"
27#include "libavutil/pixdesc.h"
29
30#include "config_components.h"
31#include "avcodec.h"
32#include "cbs.h"
33#include "cbs_av1.h"
34#include "av1_levels.h"
35#include "codec_internal.h"
36#include "d3d12va_encode.h"
37#include "encode.h"
38#include "hw_base_encode.h"
39
40#include <d3d12.h>
41#include <d3d12video.h>
42
43/* Added in Windows SDK 10.0.26100.0; define fallbacks for older SDKs. */
44#ifndef D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION
45#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION \
46 ((D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE)5)
47#endif
48#ifndef D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION
49#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION \
50 ((D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE)6)
51#endif
52
53#ifndef D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
54#define D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX ( 0xff )
55#endif
56
62
64 int tier; // 0: Main tier, 1: High tier
65 int level; // AV1 level (2.0-7.3 map to 0-23)
66
67 int enable_cdef; // Constrained Directional Enhancement Filter
68 int enable_restoration; // loop restoration
69 int enable_superres; // super-resolution
71
74
80
84
88
90 uint8_t temporal_id;
91 uint8_t spatial_id;
92 uint8_t show_frame;
93 uint8_t frame_type;
95 uint8_t slot;
97
133
134typedef struct D3D12VAEncodeAV1Level {
135 uint8_t level;
136 D3D12_VIDEO_ENCODER_AV1_LEVELS d3d12_level;
138
140 { 0, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_0 },
141 { 1, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_1 },
142 { 2, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_2 },
143 { 3, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_3 },
144 { 4, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_0 },
145 { 5, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_1 },
146 { 6, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_2 },
147 { 7, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_3 },
148 { 8, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_0 },
149 { 9, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_1 },
150 { 10, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_2 },
151 { 11, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_3 },
152 { 12, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_0 },
153 { 13, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_1 },
154 { 14, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2 },
155 { 15, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_3 },
156 { 16, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_0 },
157 { 17, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_1 },
158 { 18, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_2 },
159 { 19, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_3 },
160 { 20, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_0 },
161 { 21, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_1 },
162 { 22, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_2 },
163 { 23, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_3 },
164};
165
167 uint64_t full;
168 uint64_t prefix;
169 uint64_t data;
171
172static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_main = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
173static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_high = D3D12_VIDEO_ENCODER_AV1_PROFILE_HIGH;
174static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_professional = D3D12_VIDEO_ENCODER_AV1_PROFILE_PROFESSIONAL;
175
176#define D3D_PROFILE_DESC(name) \
177 { sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE), { .pAV1Profile = (D3D12_VIDEO_ENCODER_AV1_PROFILE *)&profile_ ## name } }
179 { AV_PROFILE_AV1_MAIN, 8, 3, 1, 1, D3D_PROFILE_DESC(main) },
180 { AV_PROFILE_AV1_MAIN, 10, 3, 1, 1, D3D_PROFILE_DESC(main) },
181 { AV_PROFILE_AV1_HIGH, 10, 3, 1, 1, D3D_PROFILE_DESC(high) },
182 { AV_PROFILE_AV1_PROFESSIONAL, 8, 3, 1, 1, D3D_PROFILE_DESC(professional) },
183 { AV_PROFILE_AV1_PROFESSIONAL, 10, 3, 1, 1, D3D_PROFILE_DESC(professional) },
184 { AV_PROFILE_AV1_PROFESSIONAL, 12, 3, 1, 1, D3D_PROFILE_DESC(professional) },
186};
187
189 char *data, size_t *data_len,
191{
192 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
193 int err = 0;
194
195 err = ff_cbs_write_fragment_data(priv->cbc, obu);
196 if (err < 0) {
197 av_log(avctx, AV_LOG_ERROR, "Failed to write packed OBU data.\n");
198 return err;
199 }
200
201 memcpy(data, obu->data, obu->data_size);
202 *data_len = (8 * obu->data_size) - obu->data_bit_padding;
203
204 return 0;
205}
206
209 CodedBitstreamUnitType obu_type,
210 void* obu_unit)
211{
212 int err = 0;
213
214 err = ff_cbs_insert_unit_content(au, -1, obu_type, obu_unit, NULL);
215 if (err < 0) {
216 av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
217 "type = %d.\n", obu_type);
218 return err;
219 }
220 return 0;
221}
222
224 char *data, size_t *data_len)
225{
226 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
228 int err = 0;
229
232 if (err < 0)
233 goto fail;
234
235 err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
236
237fail:
238 ff_cbs_fragment_reset(obu);
239 return err;
240}
241
244 AV1RawOBU *frameheader_obu)
245{
246 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
247 AV1RawFrameHeader *fh = &frameheader_obu->obu.frame_header;
248 uint8_t *data = NULL;
249 HRESULT hr = S_OK;
250 int err = 0;
251 D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *post_encode_values = NULL;
252
253 // Update the frame header according to the picture post_encode_values
254 hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
255 if (FAILED(hr)) {
256 err = AVERROR_UNKNOWN;
257 return err;
258 }
259 uint64_t nb_subregions = FFMAX(((D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)data)->WrittenSubregionsCount, 1);
260 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tile_partition =
261 (D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *) (data +
262 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
263 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) * nb_subregions);
264
265 post_encode_values = (D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *) (data +
266 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
267 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) * nb_subregions +
268 sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES));
269
270 if (nb_subregions > 1)
271 fh->context_update_tile_id = tile_partition->ContextUpdateTileId;
272
273 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_QUANTIZATION) {
274 fh->base_q_idx = post_encode_values->Quantization.BaseQIndex;
275 fh->delta_q_y_dc = post_encode_values->Quantization.YDCDeltaQ;
276 fh->delta_q_u_dc = post_encode_values->Quantization.UDCDeltaQ;
277 fh->delta_q_u_ac = post_encode_values->Quantization.UACDeltaQ;
278 fh->delta_q_v_dc = post_encode_values->Quantization.VDCDeltaQ;
279 fh->delta_q_v_ac = post_encode_values->Quantization.VACDeltaQ;
280 fh->using_qmatrix = post_encode_values->Quantization.UsingQMatrix;
281 fh->qm_y = post_encode_values->Quantization.QMY;
282 fh->qm_u = post_encode_values->Quantization.QMU;
283 fh->qm_v = post_encode_values->Quantization.QMV;
284 }
285
286 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_LOOP_FILTER) {
287 fh->loop_filter_level[0] = post_encode_values->LoopFilter.LoopFilterLevel[0];
288 fh->loop_filter_level[1] = post_encode_values->LoopFilter.LoopFilterLevel[1];
289 fh->loop_filter_level[2] = post_encode_values->LoopFilter.LoopFilterLevelU;
290 fh->loop_filter_level[3] = post_encode_values->LoopFilter.LoopFilterLevelV;
291 fh->loop_filter_sharpness = post_encode_values->LoopFilter.LoopFilterSharpnessLevel;
292 fh->loop_filter_delta_enabled = post_encode_values->LoopFilter.LoopFilterDeltaEnabled;
294 for (int i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) {
295 fh->loop_filter_ref_deltas[i] = post_encode_values->LoopFilter.RefDeltas[i];
296 fh->update_ref_delta[i] = post_encode_values->LoopFilter.RefDeltas[i];
297 }
298 for (int i = 0; i < 2; i++) {
299 fh->loop_filter_mode_deltas[i] = post_encode_values->LoopFilter.ModeDeltas[i];
300 fh->update_mode_delta[i] = post_encode_values->LoopFilter.ModeDeltas[i];
301 }
302 }
303 }
304 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_CDEF_DATA) {
305 fh->cdef_damping_minus_3 = post_encode_values->CDEF.CdefDampingMinus3;
306 fh->cdef_bits = post_encode_values->CDEF.CdefBits;
307 for (int i = 0; i < 8; i++) {
308 fh->cdef_y_pri_strength[i] = post_encode_values->CDEF.CdefYPriStrength[i];
309 fh->cdef_y_sec_strength[i] = post_encode_values->CDEF.CdefYSecStrength[i];
310 fh->cdef_uv_pri_strength[i] = post_encode_values->CDEF.CdefUVPriStrength[i];
311 fh->cdef_uv_sec_strength[i] = post_encode_values->CDEF.CdefUVSecStrength[i];
312 }
313 }
314 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_QUANTIZATION_DELTA) {
315 fh->delta_q_present = post_encode_values->QuantizationDelta.DeltaQPresent;
316 fh->delta_q_res = post_encode_values->QuantizationDelta.DeltaQRes;
317 }
318
319 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_REFERENCE_INDICES) {
320 for (int i = 0; i < AV1_REFS_PER_FRAME; i++) {
321 fh->ref_frame_idx[i] = post_encode_values->ReferenceIndices[i];
322 }
323 }
324
325 if (priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_COMPOUND_PREDICTION_MODE) {
326 fh->reference_select = post_encode_values->CompoundPredictionType ==
327 D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_COMPOUND_REFERENCE;
328 }
329
330 if ((priv->post_encode_values_flag & D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_PRIMARY_REF_FRAME) &&
332 fh->primary_ref_frame = post_encode_values->PrimaryRefFrame;
333 }
334
335 ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
336 return 0;
337}
338
341 char *data, size_t *data_len)
342{
343 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
345 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
347 AV1RawOBU *frameheader_obu = av_mallocz(sizeof(AV1RawOBU));
348 int show_slot = 0;
349 int err = 0;
350
351 if (!frameheader_obu)
352 return AVERROR(ENOMEM);
353
354 av_fifo_read(priv->picture_header_list, frameheader_obu, 1);
355 err = d3d12va_encode_av1_update_current_frame_picture_header(avctx, pic,frameheader_obu);
356 if (err < 0) {
357 av_log(avctx, AV_LOG_ERROR, "Failed to update current frame picture header: %d.\n", err);
358 av_freep(&frameheader_obu);
359 return err;
360 }
361
362 // The DPB slot this frame refreshes (single bit for anchor P frames)
363 if (frameheader_obu->obu.frame_header.refresh_frame_flags)
364 show_slot = ff_ctz(frameheader_obu->obu.frame_header.refresh_frame_flags);
365
366 // Add the frame header OBU
367 frameheader_obu->header.obu_has_size_field = 1;
368
369 err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, frameheader_obu);
370 if (err < 0)
371 goto fail;
372 err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
373 if (err < 0)
374 goto fail;
375
376 // For hidden anchor frames, build the show_existing_frame tail OBU now
377 pic->tail_size = 0;
378 if (pic->non_independent_frame) {
379 AV1RawOBU rep_obu = { 0 };
380 AV1RawFrameHeader *rep_fh = &rep_obu.obu.frame_header;
381 size_t tail_bit_len = 0;
382
383 ff_cbs_fragment_reset(obu);
384
386 rep_obu.header.obu_has_size_field = 1;
387 rep_fh->show_existing_frame = 1;
388 rep_fh->frame_to_show_map_idx = show_slot;
389 rep_fh->frame_type = AV1_FRAME_INTER;
390 rep_fh->frame_width_minus_1 = ctx->resolution.Width - 1;
391 rep_fh->frame_height_minus_1 = ctx->resolution.Height - 1;
394
395 cbctx->seen_frame_header = 0;
396
397 err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, &rep_obu);
398 if (err < 0)
399 goto fail;
400 err = d3d12va_encode_av1_write_obu(avctx, pic->tail_data, &tail_bit_len, obu);
401 if (err < 0)
402 goto fail;
403 pic->tail_size = tail_bit_len / 8;
404 }
405
406fail:
407 ff_cbs_fragment_reset(obu);
408 av_freep(&frameheader_obu);
409 return err;
410}
411
413 uint8_t* tile_group,
414 uint32_t tile_group_size,
415 char *data, size_t *data_len)
416{
417 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
420 AV1RawTileGroup *tg = &tile_group_obu->obu.tile_group;
421 int err = 0;
422
424 tg->tg_start = 0;
425 tg->tg_end = priv->tile_cols * priv->tile_rows - 1;
426
427 tg->tile_data.data = tile_group;
428 tg->tile_data.data_ref = NULL;
429 tg->tile_data.data_size = tile_group_size;
430 tile_group_obu->header.obu_has_size_field = 1;
431 tile_group_obu->header.obu_type = AV1_OBU_TILE_GROUP;
432
434 if (err < 0)
435 goto fail;
436 err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
437
438fail:
439 ff_cbs_fragment_reset(obu);
440 return err;
441}
442
445 uint64_t tile_size_bytes,
446 uint64_t *nb_subregions_out,
447 D3D12VAEncodeAV1TileInfo **tiles_out,
448 size_t *tile_payload_size_out)
449{
450 uint8_t *meta_data = NULL;
451 HRESULT hr = S_OK;
452 int err = 0;
453
454 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *out;
455 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *subregions;
457 uint64_t nb_subregions;
458 size_t tile_payload_size = 0;
459
460 hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&meta_data);
461 if (FAILED(hr))
462 return AVERROR_EXTERNAL;
463
464 out = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)meta_data;
465 subregions = (D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *) (meta_data +
466 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA));
467
468 if (out->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
469 av_log(avctx, AV_LOG_ERROR, "AV1 encode failed: error flags %#"PRIx64".\n",
470 (uint64_t)out->EncodeErrorFlags);
471 err = AVERROR_EXTERNAL;
472 goto unmap;
473 }
474
475 nb_subregions = out->WrittenSubregionsCount;
476 if (nb_subregions == 0 || subregions[0].bSize == 0) {
477 av_log(avctx, AV_LOG_ERROR, "No subregion metadata found\n");
478 err = AVERROR(EINVAL);
479 goto unmap;
480 }
481
482 tiles = av_malloc_array(nb_subregions, sizeof(*tiles));
483 if (!tiles) {
484 err = AVERROR(ENOMEM);
485 goto unmap;
486 }
487
488 for (uint64_t i = 0; i < nb_subregions; i++) {
489 tiles[i].full = subregions[i].bSize;
490 tiles[i].prefix = subregions[i].bStartOffset;
491 tiles[i].data = subregions[i].bSize - subregions[i].bStartOffset;
492 tile_payload_size += tiles[i].data;
493 }
494 /* Every tile except the last is prefixed with a tile_size_minus_1 field. */
495 if (nb_subregions > 1)
496 tile_payload_size += (nb_subregions - 1) * tile_size_bytes;
497
498 *nb_subregions_out = nb_subregions;
499 *tiles_out = tiles;
500 *tile_payload_size_out = tile_payload_size;
501
502unmap:
503 ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
504 return err;
505}
506
509{
510 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
511 int err = 0;
512 uint8_t *ptr = NULL;
513 uint8_t *mapped_data = NULL;
514 uint8_t *tile_group_buf = NULL;
515 char *obu_buf = NULL;
516 HRESULT hr = S_OK;
517 size_t av1_pic_hd_size = 0;
518 size_t bit_len = 0;
519 size_t obu_size = 0;
520 size_t tile_payload_size = 0;
521 size_t total_size = 0;
522 size_t prev_stash_sz = 0;
523 uint64_t nb_subregions = 0;
524 int output_buffer_mapped = 0;
525
527 char pic_hd_data[MAX_PARAM_BUFFER_SIZE] = { 0 };
528
530 &nb_subregions, &tiles,
531 &tile_payload_size);
532 if (err < 0)
533 goto end;
534
535 hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void **)&mapped_data);
536 if (FAILED(hr)) {
537 err = AVERROR_UNKNOWN;
538 goto end;
539 }
540 output_buffer_mapped = 1;
541
542 tile_group_buf = av_malloc(tile_payload_size);
543 if (!tile_group_buf) {
544 err = AVERROR(ENOMEM);
545 goto end;
546 }
547
548 uint8_t *dst = tile_group_buf;
549 uint8_t *tiles_base = mapped_data + pic->aligned_header_size;
550 uint64_t src_off = 0;
551 for (uint64_t i = 0; i < nb_subregions; i++) {
552 /* Tiles are laid out contiguously by their full size; the actual
553 * tile data starts bStartOffset bytes into each subregion. */
554 uint64_t src_pos = src_off + tiles[i].prefix;
555 src_off += tiles[i].full;
556
557 if (i != nb_subregions - 1) {
558 /* Write tile_size_minus_1 as a little-endian integer */
559 uint64_t v = tiles[i].data - 1;
560 for (uint64_t b = 0; b < priv->tile_size_bytes; b++)
561 *dst++ = (v >> (8 * b)) & 0xff;
562 }
563 memcpy(dst, tiles_base + src_pos, tiles[i].data);
564 dst += tiles[i].data;
565 }
566
567 err = d3d12va_encode_av1_write_picture_header(avctx, pic, pic_hd_data, &bit_len);
568 if (err < 0) {
569 av_log(avctx, AV_LOG_ERROR, "Failed to write picture header: %d.\n", err);
570 goto end;
571 }
572 av1_pic_hd_size = bit_len / 8;
573
574 obu_buf = av_malloc(tile_payload_size + MAX_PARAM_BUFFER_SIZE);
575 if (!obu_buf) {
576 err = AVERROR(ENOMEM);
577 goto end;
578 }
579 err = d3d12va_encode_av1_write_tile_group(avctx, tile_group_buf,
580 tile_payload_size, obu_buf, &bit_len);
581 if (err < 0) {
582 av_log(avctx, AV_LOG_ERROR, "Failed to write tile group: %d.\n", err);
583 goto end;
584 }
585 obu_size = bit_len / 8;
586
587 total_size = pic->header_size + av1_pic_hd_size + obu_size;
588
589 /*
590 * Hidden anchor frame: stash its coded bytes so they will be prepended
591 * to the next visible frame's packet. Visible frame: allocate a packet
592 * large enough for any stashed hidden frame bytes followed by this
593 * frame's coded data.
594 */
595 if (pic->non_independent_frame) {
596 uint8_t *new_stash = av_realloc(priv->stash_data,
597 priv->stash_size + total_size);
598 if (!new_stash) {
599 err = AVERROR(ENOMEM);
600 goto end;
601 }
602 priv->stash_data = new_stash;
603 ptr = priv->stash_data + priv->stash_size;
604 } else {
605 prev_stash_sz = priv->stash_size;
606 err = ff_get_encode_buffer(avctx, pkt, prev_stash_sz + total_size, 0);
607 if (err < 0)
608 goto end;
609 if (prev_stash_sz) {
610 memcpy(pkt->data, priv->stash_data, prev_stash_sz);
611 av_freep(&priv->stash_data);
612 priv->stash_size = 0;
613 }
614 ptr = pkt->data + prev_stash_sz;
615 }
616
617 memcpy(ptr, mapped_data, pic->header_size);
618 ptr += pic->header_size;
619
620 memcpy(ptr, pic_hd_data, av1_pic_hd_size);
621 ptr += av1_pic_hd_size;
622
623 memcpy(ptr, obu_buf, obu_size);
624
625 if (pic->non_independent_frame)
626 priv->stash_size += total_size;
627
628 av_log(avctx, AV_LOG_DEBUG, "AV1 packet: %"PRIu64" tiles, header %d, "
629 "pic header %zu, tile group %zu, total %zu bytes.\n",
630 nb_subregions, pic->header_size, av1_pic_hd_size, obu_size, total_size);
631
632end:
633 if (output_buffer_mapped)
634 ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
635 av_freep(&tiles);
636 av_freep(&tile_group_buf);
637 av_freep(&obu_buf);
639 pic->output_buffer = NULL;
640 return err;
641}
642
644 AVCodecContext *avctx,
647{
648 AV1RawOBU *seqheader_obu = &common->raw_sequence_header;
649 AV1RawSequenceHeader *seq = &seqheader_obu->obu.sequence_header;
651
652 seq->seq_profile = avctx->profile;
655 seq->seq_tier[0] = opts->tier;
656
659 .high_bitdepth = desc->comp[0].depth == 8 ? 0 : 1,
660 .color_primaries = avctx->color_primaries,
661 .transfer_characteristics = avctx->color_trc,
662 .matrix_coefficients = avctx->colorspace,
663 .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
667 .subsampling_x = desc->log2_chroma_w,
668 .subsampling_y = desc->log2_chroma_h,
669 };
670
671 switch (avctx->chroma_sample_location) {
674 break;
677 break;
678 default:
680 break;
681 }
682
683 if (avctx->level != AV_LEVEL_UNKNOWN) {
684 seq->seq_level_idx[0] = avctx->level;
685 }
686 else {
688 float framerate;
689
690 if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
691 framerate = avctx->framerate.num / avctx->framerate.den;
692 else
693 framerate = 0;
694
695 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
696 int tile_cols = priv->tile_cols > 0 ? priv->tile_cols : 1;
697 int tile_rows = priv->tile_rows > 0 ? priv->tile_rows : 1;
698
699 level = ff_av1_guess_level(avctx->bit_rate, opts->tier,
700 base_ctx->surface_width, base_ctx->surface_height,
702 if (level) {
703 av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
704 seq->seq_level_idx[0] = level->level_idx;
705 }
706 else {
707 av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
708 "any normal level, using maximum parameters level by default.\n");
709 seq->seq_level_idx[0] = 31;
710 seq->seq_tier[0] = 1;
711 }
712 }
713
714 // Still picture mode
715 seq->still_picture = (base_ctx->gop_size == 1);
717
718 // Feature flags
719 seq->use_128x128_superblock = opts->enable_128x128_superblock;
720 seq->enable_filter_intra = opts->enable_filter_intra;
721 seq->enable_intra_edge_filter = opts->enable_intra_edge_filter;
722 seq->enable_interintra_compound = opts->enable_interintra_compound;
723 seq->enable_masked_compound = opts->enable_masked_compound;
724 seq->enable_warped_motion = opts->enable_warped_motion;
725 seq->enable_dual_filter = opts->enable_dual_filter;
726 seq->enable_order_hint = !seq->still_picture;
727 if (seq->enable_order_hint) {
729 }
730 seq->enable_jnt_comp = opts->enable_jnt_comp && seq->enable_order_hint;
731 seq->enable_ref_frame_mvs = opts->enable_ref_frame_mvs && seq->enable_order_hint;
732 seq->enable_superres = opts->enable_superres;
733 seq->enable_cdef = opts->enable_cdef;
734 seq->enable_restoration = opts->enable_restoration;
735
736 return 0;
737
738}
739
741{
742 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
744 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
745 AVD3D12VAFramesContext *hwctx = base_ctx->input_frames->hwctx;
746 AV1RawOBU *seqheader_obu = &priv->units.raw_sequence_header;
748
749 D3D12_VIDEO_ENCODER_AV1_PROFILE profile = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
750 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS level = { 0 };
751 HRESULT hr;
752 int err;
753
754 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 support = {
755 .NodeIndex = 0,
756 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
757 .InputFormat = hwctx->format,
758 .RateControl = ctx->rc,
759 .IntraRefresh = ctx->intra_refresh.Mode,
760 .SubregionFrameEncoding = ctx->subregion_mode,
761 .ResolutionsListCount = 1,
762 .pResolutionList = &ctx->resolution,
763 .CodecGopSequence = ctx->gop,
764 .MaxReferenceFramesInDPB = AV1_NUM_REF_FRAMES,
765 .CodecConfiguration = ctx->codec_conf,
766 .SuggestedProfile.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE),
767 .SuggestedProfile.pAV1Profile = &profile,
768 .SuggestedLevel.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS),
769 .SuggestedLevel.pAV1LevelSetting = &level,
770 .pResolutionDependentSupport = &ctx->res_limits,
771 .SubregionFrameEncodingData.pTilesPartition_AV1 = ctx->subregions_layout.pTilesPartition_AV1,
772 };
773
774 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
775 &support, sizeof(support));
776
777 if (FAILED(hr)) {
778 av_log(avctx, AV_LOG_ERROR, "Failed to check encoder support(%lx).\n", (long)hr);
779 return AVERROR(EINVAL);
780 }
781
782 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
783 av_log(avctx, AV_LOG_ERROR, "Driver does not support requested features. ValidationFlags: %#x\n",
784 support.ValidationFlags);
785 ff_d3d12va_encode_check_encoder_feature_flags(avctx, support.ValidationFlags);
786 return AVERROR(EINVAL);
787 }
788
789 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
790 ctx->is_texture_array = 1;
791 av_log(avctx, AV_LOG_DEBUG, "D3D12 video encode on this device uses texture array mode.\n");
792 }
793
794 // Check if the configuration with DELTA_QP is supported
795 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_DELTA_QP_AVAILABLE) {
796 base_ctx->roi_allowed = 1;
797 // Store the QP map region size from resolution limits
798 ctx->qp_map_region_size = ctx->res_limits.QPMapRegionPixelsSize;
799 av_log(avctx, AV_LOG_DEBUG, "ROI encoding is supported via delta QP "
800 "(QP map region size: %d pixels).\n", ctx->qp_map_region_size);
801 } else {
802 base_ctx->roi_allowed = 0;
803 av_log(avctx, AV_LOG_DEBUG, "ROI encoding not supported by hardware for current rate control mode \n");
804 }
805
806 // Check motion estimation precision mode support
807 if (ctx->me_precision != D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM) {
808 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_MOTION_ESTIMATION_PRECISION_MODE_LIMIT_AVAILABLE)) {
809 av_log(avctx, AV_LOG_ERROR, "Hardware does not support motion estimation "
810 "precision mode limits.\n");
811 return AVERROR(ENOTSUP);
812 }
813 av_log(avctx, AV_LOG_VERBOSE, "Hardware supports motion estimation "
814 "precision mode limits.\n");
815 }
816
817 memset(seqheader_obu, 0, sizeof(*seqheader_obu));
818 seq->seq_profile = profile;
819 seq->seq_level_idx[0] = level.Level;
820 seq->seq_tier[0] = level.Tier;
821
822 seq->max_frame_width_minus_1 = ctx->resolution.Width - 1;
823 seq->max_frame_height_minus_1 = ctx->resolution.Height - 1;
824 seq->frame_width_bits_minus_1 = av_log2(ctx->resolution.Width - 1);
825 seq->frame_height_bits_minus_1 = av_log2(ctx->resolution.Height - 1);
826
827 seqheader_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
828
829 err = d3d12va_hw_base_encode_init_params_av1(base_ctx, avctx,
830 &priv->units, &priv->unit_opts);
831 if (err < 0)
832 return err;
833
834 if (avctx->level == AV_LEVEL_UNKNOWN)
835 avctx->level = level.Level;
836
837 return 0;
838}
839
840static av_always_inline int d3d12va_encode_av1_tile_log2(int blksize, int target)
841{
842 int k;
843 for (k = 0; (blksize << k) < target; k++);
844 return k;
845}
846
848{
850 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
851 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tiles_layout;
852
853 ctx->subregions_layout.DataSize =
854 sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES);
855 tiles_layout = av_mallocz(ctx->subregions_layout.DataSize);
856 if (!tiles_layout)
857 return AVERROR(ENOMEM);
858 ctx->subregions_layout.pTilesPartition_AV1 = tiles_layout;
859
860 int use_128 = priv->unit_opts.enable_128x128_superblock;
861 int width = ctx->resolution.Width;
862 int height = ctx->resolution.Height;
863
864 int mi_cols = 2 * ((width + 7) >> 3);
865 int mi_rows = 2 * ((height + 7) >> 3);
866 int sb_cols = use_128 ? ((mi_cols + 31) >> 5) : ((mi_cols + 15) >> 4);
867 int sb_rows = use_128 ? ((mi_rows + 31) >> 5) : ((mi_rows + 15) >> 4);
868 int sb_shift = use_128 ? 5 : 4;
869 int sb_size = sb_shift + 2;
870
871 int max_tile_width_sb = AV1_MAX_TILE_WIDTH >> sb_size;
872 int max_tile_area_sb = AV1_MAX_TILE_AREA >> (2 * sb_size);
873
874 int min_log2_tile_cols = d3d12va_encode_av1_tile_log2(max_tile_width_sb, sb_cols);
875 int min_log2_tiles = FFMAX(min_log2_tile_cols,
876 d3d12va_encode_av1_tile_log2(max_tile_area_sb, sb_rows * sb_cols));
877 int max_tile_area_sb_varied;
878 int tile_width_sb, tile_height_sb, widest_tile_sb;
879 int tile_cols, tile_rows;
880 int min_tile_cols = (sb_cols + max_tile_width_sb - 1) / max_tile_width_sb;
881 int i;
882
883 if (priv->tile_cols > AV1_MAX_TILE_COLS ||
885 av_log(avctx, AV_LOG_ERROR, "Invalid tile number %dx%d, should be at "
886 "most %dx%d.\n", priv->tile_cols, priv->tile_rows,
888 return AVERROR(EINVAL);
889 }
890
891 /* Calculate tile columns. When the user did not set tile explicitly
892 * (tile_cols == 0) this fallback to the minimum valid number */
893 tile_cols = av_clip(priv->tile_cols, min_tile_cols, sb_cols);
894 if (!priv->tile_cols)
895 priv->tile_cols = tile_cols;
896 else if (priv->tile_cols != tile_cols) {
897 av_log(avctx, AV_LOG_ERROR, "Invalid tile cols %d, should be in range "
898 "of %d~%d.\n", priv->tile_cols, min_tile_cols, sb_cols);
899 return AVERROR(EINVAL);
900 }
901
903 tile_width_sb = (sb_cols + (1 << priv->tile_cols_log2) - 1) >> priv->tile_cols_log2;
904
905 if (priv->tile_rows > sb_rows) {
906 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d, should be less than "
907 "%d.\n", priv->tile_rows, sb_rows);
908 return AVERROR(EINVAL);
909 }
910
911 tile_rows = priv->tile_rows ? priv->tile_rows : 1;
912 for (; tile_rows <= sb_rows && tile_rows <= AV1_MAX_TILE_ROWS; tile_rows++) {
913 /* try uniformed tile first. */
915
916 if ((sb_cols + tile_width_sb - 1) / tile_width_sb == priv->tile_cols) {
917 for (i = 0; i < priv->tile_cols - 1; i++)
918 priv->width_in_sbs_minus_1[i] = tile_width_sb - 1;
919 priv->width_in_sbs_minus_1[i] = sb_cols - (priv->tile_cols - 1) * tile_width_sb - 1;
920
921 tile_height_sb = (sb_rows + (1 << priv->tile_rows_log2) - 1) >>
922 priv->tile_rows_log2;
923
924 if ((sb_rows + tile_height_sb - 1) / tile_height_sb == tile_rows &&
925 tile_height_sb <= max_tile_area_sb / tile_width_sb) {
926 for (i = 0; i < tile_rows - 1; i++)
927 priv->height_in_sbs_minus_1[i] = tile_height_sb - 1;
928 priv->height_in_sbs_minus_1[i] = sb_rows - (tile_rows - 1) * tile_height_sb - 1;
929
930 priv->uniform_tile_spacing = 1;
931 break;
932 }
933 }
934
935 /* Try non-uniform fallback: distribute columns/rows as evenly as possible */
936 widest_tile_sb = 0;
937 for (i = 0; i < priv->tile_cols; i++) {
938 priv->width_in_sbs_minus_1[i] =
939 (i + 1) * sb_cols / priv->tile_cols - i * sb_cols / priv->tile_cols - 1;
940 widest_tile_sb = FFMAX(widest_tile_sb, priv->width_in_sbs_minus_1[i] + 1);
941 }
942
943 if (min_log2_tiles)
944 max_tile_area_sb_varied = (sb_rows * sb_cols) >> (min_log2_tiles + 1);
945 else
946 max_tile_area_sb_varied = sb_rows * sb_cols;
947 tile_height_sb = FFMAX(1, max_tile_area_sb_varied / widest_tile_sb);
948
950 (sb_rows + tile_height_sb - 1) / tile_height_sb,
951 sb_rows)) {
952 for (i = 0; i < tile_rows; i++)
953 priv->height_in_sbs_minus_1[i] =
954 (i + 1) * sb_rows / tile_rows - i * sb_rows / tile_rows - 1;
955
956 priv->uniform_tile_spacing = 0;
957 break;
958 }
959
960 if (priv->tile_rows) {
961 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d.\n", priv->tile_rows);
962 return AVERROR(EINVAL);
963 }
964 }
965
966 priv->tile_rows = tile_rows;
967 av_log(avctx, AV_LOG_DEBUG, "Setting tile cols/rows to %d/%d.\n",
968 priv->tile_cols, priv->tile_rows);
969
971 av_log(avctx, AV_LOG_ERROR, "Resolution %dx%d requires %dx%d tiles which "
972 "exceeds the AV1 maximum of %dx%d.\n", width, height,
974 return AVERROR(EINVAL);
975 }
976
977 priv->context_update_tile_id = priv->tile_cols * priv->tile_rows - 1;
978 priv->tile_size_bytes = 4;
979
980 tiles_layout->RowCount = priv->tile_rows;
981 tiles_layout->ColCount = priv->tile_cols;
982 for (i = 0; i < priv->tile_cols; i++)
983 tiles_layout->ColWidths[i] = priv->width_in_sbs_minus_1[i] + 1;
984 for (i = 0; i < priv->tile_rows; i++)
985 tiles_layout->RowHeights[i] = priv->height_in_sbs_minus_1[i] + 1;
986 tiles_layout->ContextUpdateTileId = priv->context_update_tile_id;
987
988 ctx->num_subregions = priv->tile_cols * priv->tile_rows;
989
990 if (ctx->num_subregions <= 1)
991 ctx->subregion_mode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME;
992 else if (priv->uniform_tile_spacing)
994 else
996
997 av_log(avctx, AV_LOG_VERBOSE, "AV1 tile partition: %d cols x %d rows "
998 "(%s superblocks, %s).\n", priv->tile_cols, priv->tile_rows,
999 use_128 ? "128x128" : "64x64",
1000 ctx->num_subregions <= 1 ? "full frame" :
1001 priv->uniform_tile_spacing ? "uniform grid" : "configurable grid");
1002
1003 return 0;
1004}
1005
1007{
1008 HRESULT hr = S_OK;
1009 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1011 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1012
1013 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION *config;
1014 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1_caps;
1015
1016 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
1017 .NodeIndex = 0,
1018 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
1019 .Profile = ctx->profile->d3d12_profile,
1020 .CodecSupportLimits.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT),
1021 };
1022
1023 codec_caps.CodecSupportLimits.pAV1Support = &av1_caps;
1024
1025 hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
1026 &codec_caps, sizeof(codec_caps));
1027 if (!(SUCCEEDED(hr) && codec_caps.IsSupported))
1028 return AVERROR(EINVAL);
1029
1030 ctx->codec_conf.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION);
1031 ctx->codec_conf.pAV1Config = av_mallocz(ctx->codec_conf.DataSize);
1032 if (!ctx->codec_conf.pAV1Config)
1033 return AVERROR(ENOMEM);
1034
1035 priv->post_encode_values_flag = av1_caps.PostEncodeValuesFlags;
1036 config = ctx->codec_conf.pAV1Config;
1037
1038 config->FeatureFlags = D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_NONE;
1039 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) {
1040 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK;
1042 }
1043
1044 base_ctx->surface_width = FFALIGN(avctx->width, priv->unit_opts.enable_128x128_superblock ? 128 : 64);
1045 base_ctx->surface_height = FFALIGN(avctx->height, priv->unit_opts.enable_128x128_superblock ? 128 : 64);
1046
1047 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) {
1048 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER;
1049 priv->unit_opts.enable_loop_filter = 1;
1050 }
1051
1052 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) {
1053 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING;
1054 priv->unit_opts.enable_palette = 1;
1055 }
1056
1057 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) {
1058 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY;
1060 }
1061
1062 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS) {
1063 // Loop filter deltas
1064 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS;
1066 }
1067
1068 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) {
1069 // CDEF (Constrained Directional Enhancement Filter)
1070 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING;
1071 priv->unit_opts.enable_cdef = 1;
1072 }
1073
1074 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) {
1075 // Dual filter
1076 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER;
1077 priv->unit_opts.enable_dual_filter = 1;
1078 }
1079
1080 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) {
1081 // Joint compound prediction
1082 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP;
1083 priv->unit_opts.enable_jnt_comp = 1;
1084 }
1085
1086 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) {
1087 // Frame reference motion vectors
1088 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS;
1090 }
1091
1092 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) {
1093 // Super-resolution
1094 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION;
1095 priv->unit_opts.enable_superres = 1;
1096 }
1097
1098 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) {
1099 // Warped motion
1100 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION;
1102 }
1103
1104 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) {
1105 // Inter-intra compound prediction
1106 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND;
1108 }
1109
1110 return 0;
1111}
1112
1114{
1115 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1117 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1118 int err = 0;
1119 int fixed_qp_key, fixed_qp_inter;
1120
1121 err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_AV1, avctx);
1122 if (err < 0)
1123 return err;
1124
1125 if (ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
1126 D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
1127 int fixed_qp_b;
1128 fixed_qp_inter = av_clip_uintp2(ctx->rc_quality, 8);
1129
1130 if (avctx->i_quant_factor > 0.0)
1131 fixed_qp_key = av_clip_uintp2((avctx->i_quant_factor * fixed_qp_inter +
1132 avctx->i_quant_offset) + 0.5, 8);
1133 else
1134 fixed_qp_key = fixed_qp_inter;
1135
1136 if (avctx->b_quant_factor > 0.0)
1137 fixed_qp_b = av_clip_uintp2((avctx->b_quant_factor * fixed_qp_inter +
1138 avctx->b_quant_offset) + 0.5, 8);
1139 else
1140 fixed_qp_b = fixed_qp_inter;
1141
1142 av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
1143 "%d / %d / %d for Key / Inter / B frames.\n",
1144 fixed_qp_key, fixed_qp_inter, fixed_qp_b);
1145
1146 ctx->rc.ConfigParams.DataSize = sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
1147 cqp_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
1148 if (!cqp_ctl)
1149 return AVERROR(ENOMEM);
1150
1151 cqp_ctl->ConstantQP_FullIntracodedFrame = fixed_qp_key;
1152 cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly = fixed_qp_inter;
1153 cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_b;
1154
1155 ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
1156
1157 priv->q_idx_idr = fixed_qp_key;
1158 priv->q_idx_p = fixed_qp_inter;
1159 priv->q_idx_b = fixed_qp_b;
1160
1161 }
1162
1163 // GOP configuration for AV1
1164 ctx->gop.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE);
1165 ctx->gop.pAV1SequenceStructure = av_mallocz(ctx->gop.DataSize);
1166 if (!ctx->gop.pAV1SequenceStructure)
1167 return AVERROR(ENOMEM);
1168
1169 ctx->gop.pAV1SequenceStructure->IntraDistance = base_ctx->gop_size;
1170 ctx->gop.pAV1SequenceStructure->InterFramePeriod = base_ctx->b_per_p + 1;
1171
1172 return 0;
1173}
1174
1176{
1178 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1179 int i = 0;
1180
1181 ctx->level.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1182 ctx->level.pAV1LevelSetting = av_mallocz(ctx->level.DataSize);
1183 if (!ctx->level.pAV1LevelSetting)
1184 return AVERROR(ENOMEM);
1185
1186 if (avctx->level != AV_LEVEL_UNKNOWN) {
1187 for (i = 0; i < FF_ARRAY_ELEMS(av1_levels); i++) {
1188 if (avctx->level == av1_levels[i].level) {
1189 ctx->level.pAV1LevelSetting->Level = av1_levels[i].d3d12_level;
1190 break;
1191 }
1192 }
1193
1194 if (i == FF_ARRAY_ELEMS(av1_levels) ) {
1195 av_log(avctx, AV_LOG_ERROR, "Invalid AV1 level %d.\n", avctx->level);
1196 return AVERROR(EINVAL);
1197 }
1198 } else {
1199 ctx->level.pAV1LevelSetting->Level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
1200 avctx->level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
1201 av_log(avctx, AV_LOG_DEBUG, "Using default AV1 level 5.2\n");
1202 }
1203
1204 if (priv->tier == 1 || avctx->bit_rate > 30000000) {
1205 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
1206 av_log(avctx, AV_LOG_DEBUG, "Using AV1 High tier\n");
1207 } else {
1208 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_MAIN;
1209 av_log(avctx, AV_LOG_DEBUG, "Using AV1 Main tier\n");
1210 }
1211
1212 if (priv->tier >= 0) {
1213 ctx->level.pAV1LevelSetting->Tier = priv->tier == 0 ?
1214 D3D12_VIDEO_ENCODER_AV1_TIER_MAIN :
1215 D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
1216 }
1217
1218 av_log(avctx, AV_LOG_DEBUG, "AV1 level set to %d, tier: %s\n",
1219 ctx->level.pAV1LevelSetting->Level,
1220 ctx->level.pAV1LevelSetting->Tier == D3D12_VIDEO_ENCODER_AV1_TIER_MAIN ? "Main" : "High");
1221
1222 return 0;
1223}
1224
1226{
1227 if (!pic->pic_ctl.pAV1PicData)
1228 return;
1229
1230 av_freep(&pic->pic_ctl.pAV1PicData);
1231}
1232
1235{
1236 FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
1237 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1239 D3D12VAEncodePicture *d3d12va_pic = pic->priv;
1241 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
1242 AV1RawOBU *frameheader_obu = &priv->units.raw_frame_header;
1243 AV1RawFrameHeader *fh = &frameheader_obu->obu.frame_header;
1244
1246 D3D12VAEncodeAV1Picture *href, *href_l0, *href_l1;
1247 int i, j, phys;
1248
1249 static const int8_t default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] =
1250 { 1, 0, 0, 0, -1, 0, -1, -1 };
1251
1252 memset(frameheader_obu, 0, sizeof(*frameheader_obu));
1253
1254 frameheader_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
1255
1256 d3d12va_pic->pic_ctl.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_CODEC_DATA);
1257 d3d12va_pic->pic_ctl.pAV1PicData = av_mallocz(d3d12va_pic->pic_ctl.DataSize);
1258 if (!d3d12va_pic->pic_ctl.pAV1PicData)
1259 return AVERROR(ENOMEM);
1260
1261 for (i = 0; i < AV1_NUM_REF_FRAMES; i++) {
1262 d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i]
1263 .ReconstructedPictureResourceIndex = D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX;
1264 }
1265
1266 // Initialize frame type and reference frame management
1267 switch(pic->type) {
1270 fh->refresh_frame_flags = 0xFF;
1271 fh->base_q_idx = priv->q_idx_idr;
1272 hpic->slot = 0;
1273 hpic->last_idr_frame = pic->display_order;
1275 d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
1276 D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_SINGLE_REFERENCE;
1277 break;
1278
1281 fh->base_q_idx = priv->q_idx_p;
1283
1284 ref = pic->refs[0][pic->nb_refs[0] - 1];
1285 href = ref->codec_priv;
1286
1287 d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
1288 D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_SINGLE_REFERENCE;
1289
1290 /**
1291 * The encoder uses a simple alternating reference frame strategy:
1292 * - For P-frames, it uses the last reconstructed frame as a reference.
1293 * - To simplify the reference model of the encoder, the encoder alternates between
1294 * two reference frame slots (typically slot 0 and slot 1) for storing reconstructed
1295 * images and providing prediction references for the next frame.
1296 */
1297 if (base_ctx->ref_l0 > 1) {
1298 hpic->slot = !href->slot;
1299 } else {
1300 hpic->slot = 0;
1301 }
1302 hpic->last_idr_frame = href->last_idr_frame;
1303 fh->refresh_frame_flags = 1 << hpic->slot;
1304
1305 // Set the nearest frame in L0 as all reference frame.
1306 for (i = 0; i < AV1_REFS_PER_FRAME; i++)
1307 fh->ref_frame_idx[i] = href->slot;
1308
1309 fh->primary_ref_frame = href->slot;
1310 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
1311
1312 // Set the 2nd nearest frame in L0 as Golden frame.
1313 if (pic->nb_refs[0] > 1) {
1314 ref = pic->refs[0][pic->nb_refs[0] - 2];
1315 href = ref->codec_priv;
1316 // Reference frame index 3 is the GOLDEN_FRAME
1317 fh->ref_frame_idx[3] = href->slot;
1318 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
1319 } else if (base_ctx->ref_l0 == 1) {
1320 // Keep the other slot's order hint consistent
1321 href = pic->refs[0][0]->codec_priv;
1322 fh->ref_order_hint[!href->slot] = cbctx->ref[!href->slot].order_hint;
1323 }
1324 break;
1325
1328 fh->base_q_idx = priv->q_idx_b;
1330 fh->refresh_frame_flags = 0x0; // B-frames don't refresh any DPB slot
1331 fh->reference_select = 1; // compound prediction
1332
1333 d3d12va_pic->pic_ctl.pAV1PicData->CompoundPredictionType =
1334 D3D12_VIDEO_ENCODER_AV1_COMP_PREDICTION_TYPE_COMPOUND_REFERENCE;
1335
1336 av_assert0(pic->nb_refs[0] >= 1 && pic->nb_refs[1] >= 1);
1337
1338 // L0 reference (LAST = previous anchor)
1339 ref = pic->refs[0][pic->nb_refs[0] - 1];
1340 href_l0 = ref->codec_priv;
1341 hpic->last_idr_frame = href_l0->last_idr_frame;
1342 fh->primary_ref_frame = href_l0->slot;
1343 fh->ref_order_hint[href_l0->slot] = ref->display_order - href_l0->last_idr_frame;
1344
1345 // LAST, LAST2, LAST3, GOLDEN → L0 slot
1346 for (i = 0; i < AV1_REF_FRAME_GOLDEN; i++)
1347 fh->ref_frame_idx[i] = href_l0->slot;
1348
1349 // L1 reference (BWDREF = future anchor)
1350 ref = pic->refs[1][pic->nb_refs[1] - 1];
1351 href_l1 = ref->codec_priv;
1352 fh->ref_order_hint[href_l1->slot] = ref->display_order - href_l1->last_idr_frame;
1353
1354 // BWDREF, ALTREF2, ALTREF → L1 slot
1356 fh->ref_frame_idx[i] = href_l1->slot;
1357 break;
1358
1359 default:
1360 av_log(avctx, AV_LOG_ERROR, "Unsupported picture type %d.\n", pic->type);
1361 return AVERROR(EINVAL);
1362 }
1363
1364 // Assign ppTexture2Ds indices in list order (L0 first, then L1).
1365 for (phys = 0, i = 0; i < 2; i++) {
1366 for (j = 0; j < pic->nb_refs[i]; j++) {
1367 D3D12VAEncodeAV1Picture *hr = pic->refs[i][j]->codec_priv;
1368 d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[hr->slot]
1369 .ReconstructedPictureResourceIndex = phys++;
1370 }
1371 }
1372
1373 cbctx->seen_frame_header = 0;
1374
1375 fh->show_frame = pic->display_order <= pic->encode_order;
1377 fh->order_hint = pic->display_order - hpic->last_idr_frame;
1378 fh->frame_width_minus_1 = ctx->resolution.Width - 1;
1379 fh->frame_height_minus_1 = ctx->resolution.Height - 1;
1382 fh->is_filter_switchable = 1;
1384
1386 fh->tile_cols = priv->tile_cols;
1387 fh->tile_rows = priv->tile_rows;
1388 fh->tile_cols_log2 = priv->tile_cols_log2;
1389 fh->tile_rows_log2 = priv->tile_rows_log2;
1392 for (i = 0; i < priv->tile_cols; i++)
1394 for (i = 0; i < priv->tile_rows; i++)
1396
1397 memcpy(fh->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
1398 AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
1399
1400 if (fh->frame_type == AV1_FRAME_KEY && fh->show_frame)
1401 fh->error_resilient_mode = 1;
1402
1405
1406 d3d12va_pic->pic_ctl.pAV1PicData->FrameType = fh->frame_type;
1407 d3d12va_pic->pic_ctl.pAV1PicData->TxMode = fh->tx_mode;
1408 d3d12va_pic->pic_ctl.pAV1PicData->RefreshFrameFlags = fh->refresh_frame_flags;
1409 d3d12va_pic->pic_ctl.pAV1PicData->TemporalLayerIndexPlus1 = hpic->temporal_id + 1;
1410 d3d12va_pic->pic_ctl.pAV1PicData->SpatialLayerIndexPlus1 = hpic->spatial_id + 1;
1411 d3d12va_pic->pic_ctl.pAV1PicData->PictureIndex = pic->display_order;
1412 d3d12va_pic->pic_ctl.pAV1PicData->OrderHint = fh->order_hint;
1413 d3d12va_pic->pic_ctl.pAV1PicData->InterpolationFilter = D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
1414 d3d12va_pic->pic_ctl.pAV1PicData->PrimaryRefFrame = fh->primary_ref_frame;
1415 if (fh->error_resilient_mode)
1416 d3d12va_pic->pic_ctl.pAV1PicData->Flags |= D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
1417
1418 for (i = 0; i < AV1_REFS_PER_FRAME; i++)
1419 d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices[i] = fh->ref_frame_idx[i];
1420
1421 // Process ROI side data if present and supported
1422 if (base_ctx->roi_allowed && d3d12va_pic->qp_map && d3d12va_pic->qp_map_size > 0) {
1423 d3d12va_pic->pic_ctl.pAV1PicData->QPMapValuesCount = d3d12va_pic->qp_map_size;
1424 d3d12va_pic->pic_ctl.pAV1PicData->pRateControlQPMap = (INT16 *)d3d12va_pic->qp_map;
1425 }
1426
1427 d3d12va_pic->non_independent_frame = (pic->display_order > pic->encode_order);
1428
1430}
1431
1432
1434 .profiles = d3d12va_encode_av1_profiles,
1435
1436 .d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
1437
1438 .flags = FF_HW_FLAG_B_PICTURES |
1441
1442 .default_quality = 25,
1443
1444 .get_encoder_caps = &d3d12va_encode_av1_get_encoder_caps,
1445
1446 .configure = &d3d12va_encode_av1_configure,
1447
1448 .set_level = &d3d12va_encode_av1_set_level,
1449
1450 .set_tile = &d3d12va_encode_av1_set_tile,
1451
1452 .picture_priv_data_size = sizeof(D3D12VAEncodeAV1Picture),
1453
1454 .init_sequence_params = &d3d12va_encode_av1_init_sequence_params,
1455
1456 .init_picture_params = &d3d12va_encode_av1_init_picture_params,
1457
1458 .free_picture_params = &d3d12va_encode_av1_free_picture_params,
1459
1461
1462#ifdef CONFIG_AV1_D3D12VA_ENCODER
1463 .get_coded_data = &d3d12va_encode_av1_get_coded_data,
1464#endif
1465};
1466
1468{
1470 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1471
1472 ctx->codec = &d3d12va_encode_type_av1;
1473
1474 if (avctx->profile == AV_PROFILE_UNKNOWN)
1475 avctx->profile = priv->profile;
1476 if (avctx->level == AV_LEVEL_UNKNOWN)
1477 avctx->level = priv->level;
1478
1479 if (avctx->level != AV_LEVEL_UNKNOWN && avctx->level & ~0xff) {
1480 av_log(avctx, AV_LOG_ERROR, "Invalid level %d: must fit "
1481 "in 8-bit unsigned integer.\n", avctx->level);
1482 return AVERROR(EINVAL);
1483 }
1484
1485 if (priv->qp > 0)
1486 ctx->explicit_qp = priv->qp;
1487
1489
1490 return ff_d3d12va_encode_init(avctx);
1491}
1492
1494{
1495 D3D12VAEncodeAV1Context *priv = avctx->priv_data;
1496
1497 ff_cbs_fragment_free(&priv->current_obu);
1498 ff_cbs_close(&priv->cbc);
1499
1500 av_freep(&priv->common.codec_conf.pAV1Config);
1501 av_freep(&priv->common.gop.pAV1SequenceStructure);
1502 av_freep(&priv->common.level.pAV1LevelSetting);
1503 av_freep(&priv->common.subregions_layout.pTilesPartition_AV1);
1504
1506 av_freep(&priv->stash_data);
1507
1508 return ff_d3d12va_encode_close(avctx);
1509}
1510
1511#define OFFSET(x) offsetof(D3D12VAEncodeAV1Context, x)
1512#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1517
1518 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1519 OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, FLAGS },
1520
1521 { "profile", "Set profile (general_profile_idc)",
1523 { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xff, FLAGS, "profile" },
1524
1525#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1526 { .i64 = value }, 0, 0, FLAGS, "profile"
1527 { PROFILE("main", AV_PROFILE_AV1_MAIN) },
1528 { PROFILE("high", AV_PROFILE_AV1_HIGH) },
1529 { PROFILE("professional", AV_PROFILE_AV1_PROFESSIONAL) },
1530#undef PROFILE
1531
1532 { "tier", "Set tier (general_tier_flag)",
1533 OFFSET(unit_opts.tier), AV_OPT_TYPE_INT,
1534 { .i64 = 0 }, 0, 1, FLAGS, "tier" },
1535 { "main", NULL, 0, AV_OPT_TYPE_CONST,
1536 { .i64 = 0 }, 0, 0, FLAGS, "tier" },
1537 { "high", NULL, 0, AV_OPT_TYPE_CONST,
1538 { .i64 = 1 }, 0, 0, FLAGS, "tier" },
1539
1540 { "level", "Set level (general_level_idc)",
1542 { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },
1543
1544#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1545 { .i64 = value }, 0, 0, FLAGS, "level"
1546 { LEVEL("2.0", 0) },
1547 { LEVEL("2.1", 1) },
1548 { LEVEL("2.2", 2) },
1549 { LEVEL("2.3", 3) },
1550 { LEVEL("3.0", 4) },
1551 { LEVEL("3.1", 5) },
1552 { LEVEL("3.2", 6) },
1553 { LEVEL("3.3", 7) },
1554 { LEVEL("4.0", 8) },
1555 { LEVEL("4.1", 9) },
1556 { LEVEL("4.2", 10) },
1557 { LEVEL("4.3", 11) },
1558 { LEVEL("5.0", 12) },
1559 { LEVEL("5.1", 13) },
1560 { LEVEL("5.2", 14) },
1561 { LEVEL("5.3", 15) },
1562 { LEVEL("6.0", 16) },
1563 { LEVEL("6.1", 17) },
1564 { LEVEL("6.2", 18) },
1565 { LEVEL("6.3", 19) },
1566 { LEVEL("7.0", 20) },
1567 { LEVEL("7.1", 21) },
1568 { LEVEL("7.2", 22) },
1569 { LEVEL("7.3", 23) },
1570#undef LEVEL
1571
1572 { "tiles", "Tile columns x rows (Use minimal tile column/row number "
1573 "automatically by default)",
1574 OFFSET(tile_cols), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS },
1575
1576 { NULL },
1577};
1578
1580 { "b", "0" },
1581 { "bf", "2" },
1582 { "g", "120" },
1583 { "i_qfactor", "1" },
1584 { "i_qoffset", "0" },
1585 { "b_qfactor", "1" },
1586 { "b_qoffset", "0" },
1587 { "qmin", "-1" },
1588 { "qmax", "-1" },
1589 { "refs", "0" },
1590 { NULL },
1591};
1592
1594 .class_name = "av1_d3d12va",
1595 .item_name = av_default_item_name,
1597 .version = LIBAVUTIL_VERSION_INT,
1598};
1599
1601 .p.name = "av1_d3d12va",
1602 CODEC_LONG_NAME("D3D12VA av1 encoder"),
1603 .p.type = AVMEDIA_TYPE_VIDEO,
1604 .p.id = AV_CODEC_ID_AV1,
1605 .priv_data_size = sizeof(D3D12VAEncodeAV1Context),
1608 .close = &d3d12va_encode_av1_close,
1609 .p.priv_class = &d3d12va_encode_av1_class,
1610 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
1612 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
1614 .defaults = d3d12va_encode_av1_defaults,
1616 .hw_configs = ff_d3d12va_encode_hw_configs,
1617 .p.wrapper_name = "d3d12va",
1618};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
const FFCodec ff_av1_d3d12va_encoder
static FILE * out
static AVFormatContext * ctx
static AVDictionary * opts
const AV1LevelDescriptor * ff_av1_guess_level(int64_t bitrate, int tier, int width, int height, int tiles, int tile_cols, float fps)
Guess the level of a stream from some parameters.
Definition av1_levels.c:48
static const AV1LevelDescriptor av1_levels[]
ignore entries which named in spec but no details.
Definition av1_levels.c:26
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.
static int FUNC tile_group_obu(CodedBitstreamContext *ctx, RWContext *rw, AV1RawTileGroup *current)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FLAGS
Definition cmdutils.c:598
#define CODEC_PIXFMTS(...)
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
#define FF_CODEC_RECEIVE_PACKET_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal and external API header
#define av_clip
Definition common.h:100
#define av_clip_uintp2
Definition common.h:124
#define NULL
Definition coverity.c:32
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
void ff_d3d12va_encode_check_encoder_feature_flags(void *log_ctx, D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags)
const AVCodecHWConfigInternal *const ff_d3d12va_encode_hw_configs[]
int ff_d3d12va_encode_init(AVCodecContext *avctx)
int ff_d3d12va_encode_close(AVCodecContext *avctx)
#define D3D12VA_ENCODE_RC_OPTIONS
#define D3D12VA_ENCODE_COMMON_OPTIONS
#define MAX_PARAM_BUFFER_SIZE
#define D3D_PROFILE_DESC(name)
static int d3d12va_encode_av1_get_coded_data(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AVPacket *pkt)
static int d3d12va_encode_av1_set_level(AVCodecContext *avctx)
static const AVOption d3d12va_encode_av1_options[]
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_professional
static av_always_inline int d3d12va_encode_av1_tile_log2(int blksize, int target)
static int d3d12va_encode_av1_get_encoder_caps(AVCodecContext *avctx)
static int d3d12va_encode_av1_get_buffer_size(AVCodecContext *avctx, D3D12VAEncodePicture *pic, uint64_t tile_size_bytes, uint64_t *nb_subregions_out, D3D12VAEncodeAV1TileInfo **tiles_out, size_t *tile_payload_size_out)
#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION
static int d3d12va_encode_av1_init(AVCodecContext *avctx)
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_main
#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION
static int d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
static const D3D12VAEncodeType d3d12va_encode_type_av1
static int d3d12va_encode_av1_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len)
#define LEVEL(name, value)
static int d3d12va_encode_av1_write_picture_header(AVCodecContext *avctx, D3D12VAEncodePicture *pic, char *data, size_t *data_len)
static int d3d12va_encode_av1_set_tile(AVCodecContext *avctx)
static int d3d12va_hw_base_encode_init_params_av1(FFHWBaseEncodeContext *base_ctx, AVCodecContext *avctx, D3D12VAHWBaseEncodeAV1 *common, D3D12VAHWBaseEncodeAV1Opts *opts)
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_high
static const FFCodecDefault d3d12va_encode_av1_defaults[]
static int d3d12va_encode_av1_add_obu(AVCodecContext *avctx, CodedBitstreamFragment *au, CodedBitstreamUnitType obu_type, void *obu_unit)
static int d3d12va_encode_av1_write_tile_group(AVCodecContext *avctx, uint8_t *tile_group, uint32_t tile_group_size, char *data, size_t *data_len)
static int d3d12va_encode_av1_close(AVCodecContext *avctx)
static const AVClass d3d12va_encode_av1_class
#define PROFILE(name, value)
static int d3d12va_encode_av1_configure(AVCodecContext *avctx)
#define OFFSET(x)
#define D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
static int d3d12va_encode_av1_write_obu(AVCodecContext *avctx, char *data, size_t *data_len, CodedBitstreamFragment *obu)
static const D3D12VAEncodeProfile d3d12va_encode_av1_profiles[]
static int d3d12va_encode_av1_init_sequence_params(AVCodecContext *avctx)
static void d3d12va_encode_av1_free_picture_params(D3D12VAEncodePicture *pic)
static int d3d12va_encode_av1_update_current_frame_picture_header(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AV1RawOBU *frameheader_obu)
#define AV_PROFILE_AV1_HIGH
Definition defs.h:170
#define AV_PROFILE_UNKNOWN
Definition defs.h:65
#define AV_LEVEL_UNKNOWN
Definition defs.h:209
#define AV_PROFILE_AV1_MAIN
Definition defs.h:169
#define AV_PROFILE_AV1_PROFESSIONAL
Definition defs.h:171
static AVPacket * pkt
int high
Definition dovi_rpuenc.c:39
int main
Definition dovi_rpuenc.c:38
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
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition opt.h:302
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
Definition codec.h:133
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
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 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(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_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
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#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
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
#define ff_ctz
Definition intmath.h:105
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
int tile_rows
#define HW_BASE_ENCODE_COMMON_OPTIONS
@ FF_HW_FLAG_NON_IDR_KEY_PICTURES
@ FF_HW_FLAG_TIMESTAMP_NO_DELAY
@ FF_HW_FLAG_B_PICTURES
@ FF_HW_PICTURE_TYPE_P
@ FF_HW_PICTURE_TYPE_B
@ FF_HW_PICTURE_TYPE_IDR
#define b
Definition input.c:43
#define av_log2
Definition intmath.h:84
@ AV1_TX_MODE_LARGEST
Definition av1.h:182
@ AV1_TX_MODE_SELECT
Definition av1.h:183
@ AV1_REF_FRAME_GOLDEN
Definition av1.h:66
@ AV1_OBU_TILE_GROUP
Definition av1.h:33
@ AV1_OBU_FRAME_HEADER
Definition av1.h:32
@ AV1_OBU_SEQUENCE_HEADER
Definition av1.h:30
@ AV1_FRAME_KEY
Definition av1.h:53
@ AV1_FRAME_INTER
Definition av1.h:54
@ AV1_CSP_COLOCATED
Definition av1.h:135
@ AV1_CSP_VERTICAL
Definition av1.h:134
@ AV1_CSP_UNKNOWN
Definition av1.h:133
@ AV1_MAX_TILE_WIDTH
Definition av1.h:79
@ AV1_PRIMARY_REF_NONE
Definition av1.h:87
@ AV1_NUM_REF_FRAMES
Definition av1.h:84
@ AV1_INTERPOLATION_FILTER_SWITCHABLE
Definition av1.h:104
@ AV1_MAX_TILE_COLS
Definition av1.h:82
@ AV1_SELECT_INTEGER_MV
Definition av1.h:99
@ AV1_REFS_PER_FRAME
Definition av1.h:85
@ AV1_TOTAL_REFS_PER_FRAME
Definition av1.h:86
@ AV1_MAX_TILE_ROWS
Definition av1.h:81
@ AV1_MAX_TILE_AREA
Definition av1.h:80
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Definition cbs.h:66
#define av_always_inline
Definition attributes.h:72
const char * desc
Definition libsvtav1.c:83
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
const char data[16]
Definition mxf.c:149
int profile
Definition mxfenc.c:2299
#define av_realloc(p, s)
Definition ops_static.c:54
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AVCHROMA_LOC_TOPLEFT
ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2.
Definition pixfmt.h:806
@ AVCHROMA_LOC_LEFT
MPEG-2/4 4:2:0, H.264 default for 4:2:0.
Definition pixfmt.h:804
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
Definition pixfmt.h:440
@ AVCOL_PRI_UNSPECIFIED
Definition pixfmt.h:645
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:709
#define FF_ARRAY_ELEMS(a)
uint8_t chroma_sample_position
Definition cbs_av1.h:63
uint8_t frame_type
Definition cbs_av1.h:180
uint8_t update_mode_delta[2]
Definition cbs_av1.h:270
uint8_t base_q_idx
Definition cbs_av1.h:239
uint8_t cdef_uv_pri_strength[8]
Definition cbs_av1.h:277
int8_t delta_q_v_ac
Definition cbs_av1.h:245
uint16_t render_height_minus_1
Definition cbs_av1.h:203
uint8_t using_qmatrix
Definition cbs_av1.h:246
uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS]
Definition cbs_av1.h:230
uint8_t tile_rows_log2
Definition cbs_av1.h:226
uint8_t loop_filter_delta_enabled
Definition cbs_av1.h:266
uint8_t loop_filter_level[4]
Definition cbs_av1.h:264
int8_t ref_frame_idx[AV1_REFS_PER_FRAME]
Definition cbs_av1.h:213
uint8_t is_filter_switchable
Definition cbs_av1.h:217
uint8_t cdef_y_pri_strength[8]
Definition cbs_av1.h:275
uint8_t tx_mode
Definition cbs_av1.h:284
int8_t delta_q_v_dc
Definition cbs_av1.h:244
uint16_t tile_rows
Definition cbs_av1.h:237
uint8_t showable_frame
Definition cbs_av1.h:182
uint16_t tile_cols
Definition cbs_av1.h:236
uint8_t reference_select
Definition cbs_av1.h:285
uint8_t tile_size_bytes_minus1
Definition cbs_av1.h:232
int8_t delta_q_u_ac
Definition cbs_av1.h:243
uint8_t uniform_tile_spacing_flag
Definition cbs_av1.h:224
int8_t delta_q_y_dc
Definition cbs_av1.h:240
uint8_t frame_to_show_map_idx
Definition cbs_av1.h:176
uint8_t cdef_bits
Definition cbs_av1.h:274
uint16_t render_width_minus_1
Definition cbs_av1.h:202
uint8_t delta_q_present
Definition cbs_av1.h:258
uint8_t cdef_damping_minus_3
Definition cbs_av1.h:273
uint8_t interpolation_filter
Definition cbs_av1.h:218
uint16_t frame_height_minus_1
Definition cbs_av1.h:198
uint8_t delta_q_res
Definition cbs_av1.h:259
int8_t delta_q_u_dc
Definition cbs_av1.h:242
int8_t loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME]
Definition cbs_av1.h:269
uint8_t update_ref_delta[AV1_TOTAL_REFS_PER_FRAME]
Definition cbs_av1.h:268
uint8_t refresh_frame_flags
Definition cbs_av1.h:207
uint8_t loop_filter_sharpness
Definition cbs_av1.h:265
uint8_t ref_order_hint[AV1_NUM_REF_FRAMES]
Definition cbs_av1.h:209
uint8_t show_existing_frame
Definition cbs_av1.h:175
uint8_t show_frame
Definition cbs_av1.h:181
uint8_t primary_ref_frame
Definition cbs_av1.h:196
uint8_t error_resilient_mode
Definition cbs_av1.h:184
uint8_t order_hint
Definition cbs_av1.h:191
uint16_t context_update_tile_id
Definition cbs_av1.h:231
uint16_t frame_width_minus_1
Definition cbs_av1.h:197
int8_t loop_filter_mode_deltas[2]
Definition cbs_av1.h:271
uint8_t cdef_uv_sec_strength[8]
Definition cbs_av1.h:278
uint8_t tile_cols_log2
Definition cbs_av1.h:225
uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS]
Definition cbs_av1.h:229
uint8_t cdef_y_sec_strength[8]
Definition cbs_av1.h:276
uint8_t obu_has_size_field
Definition cbs_av1.h:42
uint8_t obu_type
Definition cbs_av1.h:40
AV1RawFrameHeader frame_header
Definition cbs_av1.h:420
AV1RawOBUHeader header
Definition cbs_av1.h:414
AV1RawSequenceHeader sequence_header
Definition cbs_av1.h:419
union AV1RawOBU::@016362317061177152367125047142162076164261250366 obu
uint8_t use_128x128_superblock
Definition cbs_av1.h:114
uint8_t enable_ref_frame_mvs
Definition cbs_av1.h:124
uint8_t enable_dual_filter
Definition cbs_av1.h:120
uint8_t enable_restoration
Definition cbs_av1.h:135
uint8_t reduced_still_picture_header
Definition cbs_av1.h:85
uint8_t enable_intra_edge_filter
Definition cbs_av1.h:116
uint16_t max_frame_height_minus_1
Definition cbs_av1.h:108
uint8_t enable_filter_intra
Definition cbs_av1.h:115
uint8_t seq_force_integer_mv
Definition cbs_av1.h:129
uint8_t seq_profile
Definition cbs_av1.h:83
uint8_t enable_jnt_comp
Definition cbs_av1.h:123
uint8_t enable_interintra_compound
Definition cbs_av1.h:117
AV1RawColorConfig color_config
Definition cbs_av1.h:137
uint8_t enable_masked_compound
Definition cbs_av1.h:118
uint8_t still_picture
Definition cbs_av1.h:84
uint8_t enable_superres
Definition cbs_av1.h:133
uint8_t frame_height_bits_minus_1
Definition cbs_av1.h:106
uint8_t enable_warped_motion
Definition cbs_av1.h:119
uint8_t order_hint_bits_minus_1
Definition cbs_av1.h:131
uint8_t frame_width_bits_minus_1
Definition cbs_av1.h:105
uint8_t seq_tier[AV1_MAX_OPERATING_POINTS]
Definition cbs_av1.h:97
uint8_t seq_level_idx[AV1_MAX_OPERATING_POINTS]
Definition cbs_av1.h:96
uint16_t max_frame_width_minus_1
Definition cbs_av1.h:107
uint8_t enable_order_hint
Definition cbs_av1.h:122
uint8_t seq_force_screen_content_tools
Definition cbs_av1.h:127
uint8_t * data
Definition cbs_av1.h:301
size_t data_size
Definition cbs_av1.h:303
AVBufferRef * data_ref
Definition cbs_av1.h:302
uint16_t tg_start
Definition cbs_av1.h:312
AV1RawTileData tile_data
Definition cbs_av1.h:315
uint8_t tile_start_and_end_present_flag
Definition cbs_av1.h:311
uint16_t tg_end
Definition cbs_av1.h:313
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition avcodec.h:681
float b_quant_offset
qscale offset between IP and B-frames
Definition avcodec.h:797
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
Definition avcodec.h:657
float b_quant_factor
qscale factor between IP and B-frames If > 0 then the last P-frame quantizer will be used (q= lastp_q...
Definition avcodec.h:790
AVRational framerate
Definition avcodec.h:563
int level
Encoding level descriptor.
Definition avcodec.h:1646
int64_t bit_rate
the average bitrate
Definition avcodec.h:493
int profile
profile
Definition avcodec.h:1636
enum AVColorSpace colorspace
YUV colorspace type.
Definition avcodec.h:671
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition avcodec.h:664
enum AVChromaLocation chroma_sample_location
This defines the location of chroma samples.
Definition avcodec.h:688
float i_quant_factor
qscale factor between P- and I-frames If > 0 then the last P-frame quantizer will be used (q = lastp_...
Definition avcodec.h:806
void * priv_data
Definition avcodec.h:470
float i_quant_offset
qscale offset between P and I-frames
Definition avcodec.h:813
This struct is allocated as AVHWFramesContext.hwctx.
DXGI_FORMAT format
DXGI_FORMAT format.
Definition fifo.c:35
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
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
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
AV1ReferenceFrameState ref[AV1_NUM_REF_FRAMES]
Definition cbs_av1.h:491
Context structure for coded bitstream operations.
Definition cbs.h:226
void * priv_data
Internal codec-specific data.
Definition cbs.h:247
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
size_t data_bit_padding
The number of bits which should be ignored in the final byte.
Definition cbs.h:146
size_t data_size
The number of bytes in the bitstream.
Definition cbs.h:142
uint8_t * data
Pointer to the bitstream form of this fragment.
Definition cbs.h:135
D3D12VAHWBaseEncodeAV1Opts unit_opts
CodedBitstreamFragment current_obu
D3D12VAHWBaseEncodeAV1 units
uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS]
CodedBitstreamContext * cbc
D3D12VAEncodeContext common
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAGS post_encode_values_flag
uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS]
D3D12_VIDEO_ENCODER_AV1_LEVELS d3d12_level
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION codec_conf
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE gop
D3D12_VIDEO_ENCODER_LEVEL_SETTING level
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA subregions_layout
AVBufferRef * output_buffer_ref
char tail_data[MAX_PARAM_BUFFER_SIZE]
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl
ID3D12Resource * resolved_metadata
ID3D12Resource * output_buffer
AVHWFramesContext * input_frames
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_malloc_array(a, b)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
int tiles
Definition av1_levels.c:72
float framerate
Definition av1_levels.c:29
int tile_cols
Definition av1_levels.c:73
static int ref[MAX_W *MAX_W]
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
color_range
static int write_sequence_header(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, uint8_t *data, size_t *data_len)