FFmpeg
Loading...
Searching...
No Matches
apv_encode_vulkan.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2026 Lynne <dev@lynne.ee>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <math.h>
22#include <stdlib.h>
23
24#include "libavutil/mem.h"
25#include "libavutil/opt.h"
26#include "libavutil/pixdesc.h"
27#include "libavutil/vulkan.h"
28
29#include "avcodec.h"
30#include "codec_internal.h"
31#include "encode.h"
32#include "hwconfig.h"
33#include "internal.h"
34
35#include "apv.h"
36#include "cbs.h"
37#include "cbs_apv.h"
38
39extern const unsigned char ff_apv_encode_dct_comp_spv_data[];
40extern const unsigned int ff_apv_encode_dct_comp_spv_len;
41
42extern const unsigned char ff_apv_encode_tiles_comp_spv_data[];
43extern const unsigned int ff_apv_encode_tiles_comp_spv_len;
44
45extern const unsigned char ff_seg_gather_comp_spv_data[];
46extern const unsigned int ff_seg_gather_comp_spv_len;
47
48#define APV_DEFAULT_QMAT 16
49#define APV_MAX_NUM_COMP 4
50
51typedef struct DCTPushData {
52 int frame_dim[2];
53 int tile_count[2];
58 float qf[APV_MAX_NUM_COMP]; /* per-component fact/(level_scale*2^qp_shift) */
59 uint8_t qmat[64]; /* quantisation matrix, raster order */
61
62typedef struct EntropyPushData {
63 VkDeviceAddress bytestream;
64 int tile_count[2];
66 uint32_t slot_size;
67 uint32_t comp_base; /* component index this dispatch's z=0 maps to */
68 uint32_t blocks_per_tile; /* uniform coeff stride, in blocks */
69 int frame_mb[2]; /* frame size in MBs (luma basis) */
70 int tile_mb_dim[2]; /* full-tile size in MBs */
71 uint32_t blocks_per_mb; /* blocks per MB of this dispatch's components */
73
74typedef struct CompactPushData {
75 VkDeviceAddress sparse;
76 VkDeviceAddress compacted;
77 uint32_t slot_size;
79
92
93typedef struct VulkanEncodeAPVContext {
94 const AVClass *class;
95
99
101 FFVulkanShader shd_entropy[2]; /* [0] luma-sized, [1] chroma-sized */
103
104 /* Per-frame buffer pools */
110
111 /* DCT/quantize push constants -- encoder-constant, built once at init. */
113
114 /* CBS used to assemble the output packet */
117
119
120 /* Async machinery */
124
125 /* Derived per-encoder state */
126 int frame_mb_x, frame_mb_y; /* MBs in the frame (luma basis) */
128 int tile_mb_w, tile_mb_h; /* MBs per tile (luma basis) */
130 int blocks_per_mb; /* luma; always 4 */
131 int chroma_blocks_per_mb; /* 4 for 4:4:4, 2 for 4:2:2 */
135
140
141 size_t coeffs_size; /* total size of coeffs buffer */
142 size_t bytestream_size; /* total size of bytestream buffer */
143 size_t slot_size; /* per-tile-component bytestream slot size */
144 size_t sizes_size; /* total size of sizes buffer */
145
146 /* User options */
149 int qp_y;
150 int qp_c;
151 int qmatrix; /* APV_QMATRIX_*: quantisation matrix select */
152
153 /* Benchmark knob (env APV_VULKAN_HEADERS_ONLY): the GPU still encodes,
154 * but the tiles are never downloaded and packets carry headers only. */
156
157 /* Benchmark knob (env APV_VULKAN_SKIP_ENTROPY): skip the entropy
158 * dispatch to isolate the DCT pass. Implies headers_only. */
161
162/*
163 * HEVC default 8x8 intra scaling list (ITU-T H.265, Table 7-6): flat through
164 * the low-frequency core, a gentle ramp toward the high-frequency corner.
165 * Raster order; the matrix is symmetric, so APV's [y][x]/[x][y] indexing is
166 * immaterial. APV and HEVC share the "16 = neutral" convention, so the list
167 * transfers without rescaling.
168 */
169static const uint8_t apv_qmat_hevc_intra[64] = {
170 16, 16, 16, 16, 17, 18, 21, 24,
171 16, 16, 16, 16, 17, 19, 22, 25,
172 16, 16, 17, 18, 20, 22, 25, 29,
173 16, 16, 18, 21, 24, 27, 31, 36,
174 17, 17, 20, 24, 30, 35, 41, 47,
175 18, 19, 22, 27, 35, 44, 54, 65,
176 21, 22, 25, 31, 41, 54, 70, 88,
177 24, 25, 29, 36, 47, 65, 88, 115,
178};
179
180enum {
181 APV_QMATRIX_FLAT = 0, /* uniform 16 (the spec default) */
182 APV_QMATRIX_HEVC = 1, /* HEVC default intra scaling list */
183};
184
185/*
186 * The active quantisation-matrix value at raster index i. Both the q_matrix
187 * signalled in the frame header and the encoder's pf table are derived from
188 * this single accessor, so they cannot disagree -- a mismatch would quantise
189 * against a different matrix than the decoder dequantises with.
190 */
191static int apv_qmatrix_value(int qmatrix, int i)
192{
193 return qmatrix == APV_QMATRIX_HEVC ? apv_qmat_hevc_intra[i]
195}
196
197static const uint8_t apv_level_scale[6] = { 40, 45, 51, 57, 64, 71 };
198
200{
201 switch (sw_fmt) {
214 default:
215 return -1;
216 }
217}
218
220{
221 switch (sw_fmt) {
229 default: return -1;
230 }
231}
232
234{
235 int err;
237 FFVulkanShader *shd = &ev->shd_dct;
238
239 SPEC_LIST_CREATE(sl, 1, sizeof(uint32_t))
240 SPEC_LIST_ADD(sl, 16, 32, 4); /* nb_blocks: blocks_per_mb per workgroup */
241
242 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
243 (uint32_t []) { 8, 4, 1 }, 0);
244
246 VK_SHADER_STAGE_COMPUTE_BIT);
247
248 const FFVulkanDescriptorSetBinding desc_set[] = {
249 {
250 .name = "coeffs_buf",
251 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
252 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
253 },
254 {
255 .name = "src",
256 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
257 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
259 },
260 };
261 ff_vk_shader_add_descriptor_set(&ev->s, shd, desc_set, 2, 0);
262
263 RET(ff_vk_shader_link(&ev->s, shd,
266
267 RET(ff_vk_shader_register_exec(&ev->s, &ev->exec_pool, shd));
268
269fail:
270 return err;
271}
272
273static int init_entropy_shader(AVCodecContext *avctx, int blocks_per_mb,
274 FFVulkanShader *shd)
275{
276 int err;
278
279 /* One workgroup per tile-component, one invocation per transform block.
280 * Luma and chroma tile-components hold different block counts under
281 * chroma sub-sampling, so each gets a pipeline with its own size. */
282 uint32_t wg = ev->tile_mb_w * ev->tile_mb_h * blocks_per_mb;
283
284 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
285 (uint32_t []) { wg, 1, 1 }, 0);
286
288 VK_SHADER_STAGE_COMPUTE_BIT);
289
290 const FFVulkanDescriptorSetBinding desc_set[] = {
291 {
292 .name = "coeffs_buf",
293 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
294 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
295 },
296 {
297 .name = "sizes_buf",
298 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
299 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
300 },
301 };
302 ff_vk_shader_add_descriptor_set(&ev->s, shd, desc_set, 2, 0);
303
304 RET(ff_vk_shader_link(&ev->s, shd,
307
308 RET(ff_vk_shader_register_exec(&ev->s, &ev->exec_pool, shd));
309
310fail:
311 return err;
312}
313
315{
316 int err;
318 FFVulkanShader *shd = &ev->shd_compact;
319
320 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
321 (uint32_t []) { 256, 1, 1 }, 0);
322
324 VK_SHADER_STAGE_COMPUTE_BIT);
325
326 const FFVulkanDescriptorSetBinding desc_set[] = {
327 {
328 .name = "sizes_buf",
329 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
330 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
331 },
332 };
333 ff_vk_shader_add_descriptor_set(&ev->s, shd, desc_set, 1, 0);
334
335 RET(ff_vk_shader_link(&ev->s, shd,
338
339 RET(ff_vk_shader_register_exec(&ev->s, &ev->exec_pool, shd));
340
341fail:
342 return err;
343}
344
345/*
346 * The DCT/quantize shader's push constants are entirely encoder-constant:
347 * frame geometry, the per-component quant scale qf, and the quantisation
348 * matrix. Build them once -- nothing here changes between frames.
349 */
351{
354 DCTPushData *pd = &ev->dct_push;
355 const double fact = (double)(1 << (ev->bit_depth - 1));
356
357 pd->frame_dim[0] = avctx->width;
358 pd->frame_dim[1] = avctx->height;
359 pd->tile_count[0] = ev->tile_cols;
360 pd->tile_count[1] = ev->tile_rows;
361 pd->tile_mb_dim[0] = ev->tile_mb_w;
362 pd->tile_mb_dim[1] = ev->tile_mb_h;
363 pd->log2_chroma_sub[0] = desc->log2_chroma_w;
364 pd->log2_chroma_sub[1] = desc->log2_chroma_h;
365 pd->num_comp = ev->num_comp;
366 pd->bit_depth = ev->bit_depth;
367
368 /*
369 * qf[c] = fact / (level_scale * 2^qp_shift). The encoder uses one QP per
370 * component, so this never varies by tile. Component 3 is alpha
371 * (4:4:4:4): full-resolution, so it takes the luma QP.
372 */
373 for (int c = 0; c < APV_MAX_NUM_COMP; c++) {
374 int qp = (c == 0 || c == 3) ? ev->qp_y : ev->qp_c;
375 int level_scale = apv_level_scale[qp % 6];
376 int qp_shift = qp / 6;
377 pd->qf[c] =
378 (float)(fact / ((double)level_scale * (double)(1 << qp_shift)));
379 }
380
381 /*
382 * The 8-bit quantisation matrix. The shader stages it to shared memory
383 * and quantises with 1024 / qmat[i], the reciprocal partner of the
384 * decoder's per-coefficient dequant -- the same matrix that gets
385 * signalled in the frame header.
386 */
387 for (int i = 0; i < 64; i++)
388 pd->qmat[i] = apv_qmatrix_value(ev->qmatrix, i);
389}
390
392 AVFrame *frame)
393{
394 int err = 0;
396 FFVulkanFunctions *vk = &ev->s.vkfn;
398 VkImageView views[AV_NUM_DATA_POINTERS];
399
400 VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
401 int nb_img_bar = 0;
402 VkBufferMemoryBarrier2 buf_bar[4];
403 int nb_buf_bar = 0;
404
405 FFVkBuffer *coeffs_buf;
406 FFVkBuffer *bytestream_buf;
407
408 FFVkBuffer *gathered_buf = NULL;
409 FFVkBuffer *compacted_buf;
410 FFVkBuffer *sizes_buf;
411
412 /* Start recording */
413 err = ff_vk_exec_start(&ev->s, exec);
414 if (err < 0)
415 return err;
416
417 /* Allocate per-frame buffers */
419 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
420 NULL, ev->coeffs_size,
421 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
422 coeffs_buf = fd->coeffs_ref;
423
424 /* The entropy shader writes the bitstream here, sparsely -- one
425 * worst-case-sized slot per tile-component. Device-local, so those GPU
426 * writes stay in VRAM and never cross PCIe. */
428 &fd->bytestream_ref,
429 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
430 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
432 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
433 bytestream_buf = fd->bytestream_ref;
434
435 /* The compaction shader gathers the sparse slots into here, contiguous.
436 * Device-local: shader stores over the bus are unreliably slow on some
437 * drivers, so the transfer to the host is left to the copy engine. */
439 &gathered_buf,
440 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
441 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
442 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
444 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
445
446 /* Copy-engine destination the CPU assembles the packet from.
447 * Host-visible + host-cached so the readback is a fast cached copy. */
449 &fd->compacted_ref,
450 VK_BUFFER_USAGE_TRANSFER_DST_BIT |
451 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
452 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
454 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
455 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
456 compacted_buf = fd->compacted_ref;
457
459 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
460 NULL, ev->sizes_size,
461 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
462 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
463 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
464 sizes_buf = fd->sizes_ref;
465
470
472 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
473 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
474
475 RET(ff_vk_create_imageviews(&ev->s, exec, views, frame, FF_VK_REP_INT));
476
477 ff_vk_frame_barrier(&ev->s, exec, frame,
478 img_bar, &nb_img_bar,
479 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
480 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
481 VK_ACCESS_SHADER_READ_BIT,
482 VK_IMAGE_LAYOUT_GENERAL,
483 VK_QUEUE_FAMILY_IGNORED);
484
485 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
486 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
487 .pImageMemoryBarriers = img_bar,
488 .imageMemoryBarrierCount = nb_img_bar,
489 });
490 nb_img_bar = 0;
491
492 /* DCT + Quantize pass */
493 {
495 0, 0, 0,
496 coeffs_buf, 0, coeffs_buf->size,
497 VK_FORMAT_UNDEFINED);
498 ff_vk_shader_update_img_array(&ev->s, exec, &ev->shd_dct,
499 frame, views,
500 0, 1,
501 VK_IMAGE_LAYOUT_GENERAL,
502 VK_NULL_HANDLE);
503
504 ff_vk_exec_bind_shader(&ev->s, exec, &ev->shd_dct);
506 VK_SHADER_STAGE_COMPUTE_BIT,
507 0, sizeof(ev->dct_push), &ev->dct_push);
508
509 vk->CmdDispatch(exec->buf,
510 ev->frame_mb_x, ev->frame_mb_y, ev->num_comp);
511 }
512
513 /* Barrier: wait for coeff writes before entropy */
514 ff_vk_buf_barrier(buf_bar[nb_buf_bar++], coeffs_buf,
515 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE,
516 COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE,
517 0, coeffs_buf->size);
518
519 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
520 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
521 .pBufferMemoryBarriers = buf_bar,
522 .bufferMemoryBarrierCount = nb_buf_bar,
523 });
524 nb_buf_bar = 0;
525
526 /*
527 * Entropy encoding pass. Luma (component 0) and chroma (components
528 * 1..num_comp-1) run as two dispatches: under chroma sub-sampling their
529 * tile-components hold different block counts, hence different workgroup
530 * sizes -- one pipeline each. The two write disjoint memory and need no
531 * barrier between them, so the GPU is free to overlap them.
532 */
533 for (int p = 0; !ev->skip_entropy && p < 2; p++) {
534 FFVulkanShader *shd = &ev->shd_entropy[p];
535 uint32_t z_comps = (p == 0) ? 1 : ev->num_comp - 1;
536
537 if (z_comps == 0)
538 continue; /* 4:0:0 (monochrome) has no chroma components */
539
540 EntropyPushData pd = {
541 .bytestream = bytestream_buf->address,
542 .tile_count = { ev->tile_cols, ev->tile_rows },
543 .num_comp = ev->num_comp,
544 .slot_size = (uint32_t)ev->slot_size,
545 .comp_base = (uint32_t)p,
546 .blocks_per_tile = (uint32_t)ev->tile_mb_w * ev->tile_mb_h *
547 ev->blocks_per_mb,
548 .frame_mb = { ev->frame_mb_x, ev->frame_mb_y },
549 .tile_mb_dim = { ev->tile_mb_w, ev->tile_mb_h },
550 .blocks_per_mb = (uint32_t)(p == 0 ? ev->blocks_per_mb
552 };
553
554 ff_vk_shader_update_desc_buffer(&ev->s, exec, shd, 0, 0, 0,
555 coeffs_buf, 0, coeffs_buf->size,
556 VK_FORMAT_UNDEFINED);
557 ff_vk_shader_update_desc_buffer(&ev->s, exec, shd, 0, 1, 0,
558 sizes_buf, 0, sizes_buf->size,
559 VK_FORMAT_UNDEFINED);
560
561 ff_vk_exec_bind_shader(&ev->s, exec, shd);
562 ff_vk_shader_update_push_const(&ev->s, exec, shd,
563 VK_SHADER_STAGE_COMPUTE_BIT,
564 0, sizeof(pd), &pd);
565
566 vk->CmdDispatch(exec->buf, ev->tile_cols, ev->tile_rows, z_comps);
567 }
568
569 /* Compaction pass: gather the sparse per-tile-component slots into one
570 * contiguous device-local buffer, then read it back with the copy
571 * engine. */
572 if (!ev->headers_only) {
573 ff_vk_buf_barrier(buf_bar[nb_buf_bar++], bytestream_buf,
574 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE,
575 COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE,
576 0, bytestream_buf->size);
577 ff_vk_buf_barrier(buf_bar[nb_buf_bar++], sizes_buf,
578 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE,
579 COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE,
580 0, sizes_buf->size);
581 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
582 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
583 .pBufferMemoryBarriers = buf_bar,
584 .bufferMemoryBarrierCount = nb_buf_bar,
585 });
586 nb_buf_bar = 0;
587
588 CompactPushData pd = {
589 .sparse = bytestream_buf->address,
590 .compacted = gathered_buf->address,
591 .slot_size = (uint32_t)ev->slot_size,
592 };
593
594 ff_vk_shader_update_desc_buffer(&ev->s, exec, &ev->shd_compact,
595 0, 0, 0,
596 sizes_buf, 0, sizes_buf->size,
597 VK_FORMAT_UNDEFINED);
598 ff_vk_exec_bind_shader(&ev->s, exec, &ev->shd_compact);
599 ff_vk_shader_update_push_const(&ev->s, exec, &ev->shd_compact,
600 VK_SHADER_STAGE_COMPUTE_BIT,
601 0, sizeof(pd), &pd);
602
603 vk->CmdDispatch(exec->buf, ev->tile_count * ev->num_comp, 1, 1);
604
605 /* The gathered size is only known once the encode is done, so the
606 * whole buffer is copied; the slots are sized to the entropy coder's
607 * worst case, which keeps this close to the payload size. */
608 ff_vk_buf_barrier(buf_bar[nb_buf_bar++], gathered_buf,
609 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE,
610 TRANSFER_BIT, TRANSFER_READ_BIT, NONE,
611 0, gathered_buf->size);
612 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
613 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
614 .pBufferMemoryBarriers = buf_bar,
615 .bufferMemoryBarrierCount = nb_buf_bar,
616 });
617 nb_buf_bar = 0;
618
619 vk->CmdCopyBuffer(exec->buf, gathered_buf->buf, compacted_buf->buf,
620 1, &(VkBufferCopy) { .size = ev->bytestream_size });
621 }
622
623 ff_vk_exec_move_dep_refstruct(&ev->s, exec, &gathered_buf);
624 err = ff_vk_exec_submit(&ev->s, exec);
625 if (err < 0)
626 return err;
627
628 return 0;
629
630fail:
631 av_refstruct_unref(&gathered_buf);
632 ff_vk_exec_discard(&ev->s, exec);
633 return err;
634}
635
637 AVPacket *pkt)
638{
639 int err = 0;
641 FFVulkanFunctions *vk = &ev->s.vkfn;
643 FFVkBuffer *compacted_buf = fd->compacted_ref;
644 FFVkBuffer *sizes_buf = fd->sizes_ref;
645 APVRawFrame *raw_frame = NULL;
646
647 /* Wait for the GPU encode to finish */
648 ff_vk_exec_wait(&ev->s, exec);
649
650 const uint32_t *sizes = NULL;
651 static uint8_t headers_only_tile; /* 1-byte token tile data */
652
653 /* Headers-only benchmark mode never touches the GPU output. */
654 if (!ev->headers_only) {
655 /* Invalidate mapped memory if needed */
656 if (!(compacted_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
657 VkMappedMemoryRange r = {
658 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
659 .memory = compacted_buf->mem,
660 .offset = 0,
661 .size = VK_WHOLE_SIZE,
662 };
663 vk->InvalidateMappedMemoryRanges(ev->s.hwctx->act_dev, 1, &r);
664 }
665 if (!(sizes_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
666 VkMappedMemoryRange r = {
667 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
668 .memory = sizes_buf->mem,
669 .offset = 0,
670 .size = VK_WHOLE_SIZE,
671 };
672 vk->InvalidateMappedMemoryRanges(ev->s.hwctx->act_dev, 1, &r);
673 }
674 sizes = (const uint32_t *)sizes_buf->mapped_mem;
675 }
676
677 /* Allocate the cbs frame structure */
678 raw_frame = av_mallocz(sizeof(*raw_frame));
679 if (!raw_frame)
680 return AVERROR(ENOMEM);
681
683 raw_frame->pbu_header.group_id = 1;
684
685 APVRawFrameHeader *fh = &raw_frame->frame_header;
688 fh->frame_info.band_idc = ev->band_idc;
689 fh->frame_info.frame_width = avctx->width;
690 fh->frame_info.frame_height = avctx->height;
694
696 /* Inferred values when the flag is 0, per the spec. */
697 fh->color_primaries = 2;
699 fh->matrix_coefficients = 2;
700 fh->full_range_flag = 0;
701
702 /* compute_pf_table() builds the encoder's pf scale from the same matrix;
703 * the two must stay in sync. use_q_matrix is only signalled when the
704 * matrix is non-uniform (a flat 16 matrix is the inferred default). */
706 for (int c = 0; c < ev->num_comp; c++)
707 for (int y = 0; y < 8; y++)
708 for (int x = 0; x < 8; x++)
709 fh->quantization_matrix.q_matrix[c][y][x] =
710 apv_qmatrix_value(ev->qmatrix, y * 8 + x);
711
715
716 /* Populate each tile. The compacted buffer holds each tile-component's
717 * data back to back, in (tile, component) order -- the same layout the
718 * gather shader produced. */
719 uint32_t comp_off = 0;
720 for (int t = 0; t < ev->tile_count; t++) {
721 APVRawTile *tile = &raw_frame->tile[t];
722 uint32_t total_tile_data = 0;
723
724 tile->tile_header.tile_header_size =
725 4 + ev->num_comp * (4 + 1) + 1;
726 tile->tile_header.tile_index = t;
727
728 for (int c = 0; c < ev->num_comp; c++) {
729 uint32_t sz;
730 if (ev->headers_only) {
731 /* No readback: one token byte (CBS requires size >= 1). */
732 sz = 1;
733 tile->tile_data[c] = &headers_only_tile;
734 } else {
735 sz = sizes[t * ev->num_comp + c];
736 tile->tile_data[c] = compacted_buf->mapped_mem + comp_off;
737 comp_off += sz;
738 }
739 tile->tile_header.tile_data_size[c] = sz;
740 tile->tile_header.tile_qp[c] =
741 (c == 0 || c == 3) ? ev->qp_y : ev->qp_c;
742 total_tile_data += sz;
743 }
744 tile->tile_header.reserved_zero_8bits = 0;
745 tile->tile_dummy_byte_size = 0;
746 tile->tile_dummy_byte = NULL;
747
748 raw_frame->tile_size[t] =
749 tile->tile_header.tile_header_size + total_tile_data;
750 }
751
752 /* Assemble fragment using cbs_apv */
753 ff_cbs_fragment_reset(&ev->au);
754
755 err = ff_cbs_insert_unit_content(&ev->au, -1, APV_PBU_PRIMARY_FRAME,
756 raw_frame, NULL);
757 if (err < 0) {
758 av_freep(&raw_frame);
759 return err;
760 }
761 /* raw_frame is now owned by the fragment unit */
762 raw_frame = NULL;
763
764 /* Assemble straight into the packet: ff_cbs_write_packet() hands pkt a
765 * reference to CBS's own assembled buffer -- no copy. */
766 err = ff_cbs_write_packet(ev->cbc, pkt, &ev->au);
767 if (err < 0)
768 return err;
769
770 pkt->pts = fd->pts;
771 pkt->dts = fd->pts;
772 pkt->duration = fd->duration;
773 pkt->flags |= AV_PKT_FLAG_KEY; /* APV is all intra */
774
775 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
776 pkt->opaque = fd->frame_opaque;
777 pkt->opaque_ref = fd->frame_opaque_ref;
779 }
780
781 av_log(avctx, AV_LOG_VERBOSE, "Encoded APV frame: %i bytes (%.2f MiB)\n",
782 pkt->size, pkt->size / (1024.0 * 1024.0));
783
788
789 return 0;
790}
791
793 AVPacket *pkt)
794{
795 int err;
798 FFVkExecContext *exec;
799 AVFrame *frame;
800
801 while (1) {
802 exec = ff_vk_exec_get(&ev->s, &ev->exec_pool);
803
804 if (exec->had_submission) {
805 exec->had_submission = 0;
806 ev->in_flight--;
807 return build_packet(avctx, exec, pkt);
808 }
809
810 frame = ev->frame;
811 err = ff_encode_get_frame(avctx, frame);
812 if (err < 0 && err != AVERROR_EOF)
813 return err;
814 else if (err == AVERROR_EOF) {
815 if (!ev->in_flight)
816 return err;
817 continue;
818 }
819
820 fd = exec->opaque;
821 fd->pts = frame->pts;
822 fd->duration = frame->duration;
823 fd->flags = frame->flags;
824 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
825 fd->frame_opaque = frame->opaque;
826 fd->frame_opaque_ref = frame->opaque_ref;
827 frame->opaque_ref = NULL;
828 }
829
830 err = submit_frame(avctx, exec, frame);
832 if (err < 0)
833 return err;
834
835 ev->in_flight++;
836 if (ev->in_flight < ev->async_depth)
837 return AVERROR(EAGAIN);
838 }
839 return 0;
840}
841
843{
845
846 ff_vk_exec_pool_free(&ev->s, &ev->exec_pool);
847
848 ff_vk_shader_free(&ev->s, &ev->shd_dct);
849 ff_vk_shader_free(&ev->s, &ev->shd_entropy[0]);
850 ff_vk_shader_free(&ev->s, &ev->shd_entropy[1]);
851 ff_vk_shader_free(&ev->s, &ev->shd_compact);
852
853 if (ev->exec_ctx_info) {
854 for (int i = 0; i < ev->async_depth; i++) {
861 }
863 }
864
870
871 ff_cbs_fragment_free(&ev->au);
872 ff_cbs_close(&ev->cbc);
873
874 av_frame_free(&ev->frame);
875 ff_vk_uninit(&ev->s);
876
877 return 0;
878}
879
881{
882 int err;
884 AVHWFramesContext *hwfc;
885
886 if (!avctx->hw_frames_ctx) {
887 av_log(avctx, AV_LOG_ERROR, "An AVHWFramesContext is required.\n");
888 return AVERROR(EINVAL);
889 }
890 hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
891 ev->sw_format = hwfc->sw_format;
892
895 if (ev->profile_idc < 0 || ev->chroma_format_idc < 0) {
896 av_log(avctx, AV_LOG_ERROR, "Unsupported sw_format %s for APV.\n",
898 return AVERROR(EINVAL);
899 }
900
901 /* All four APV chroma formats are supported -- 4:0:0, 4:2:2, 4:4:4 and
902 * 4:4:4:4. The profile_idc / chroma_format_idc checks above already
903 * reject any pixel format that is not one of them. */
905 ev->bit_depth = desc->comp[0].depth;
906 ev->num_comp = desc->nb_components;
907 ev->blocks_per_mb = 4; /* luma: 16x16 MB -> 4 8x8 blocks */
908 ev->chroma_blocks_per_mb = 4 >> (desc->log2_chroma_w + desc->log2_chroma_h);
909 ev->level_idc = 33; /* placeholder, real value depends on resolution and bitrate */
910 ev->band_idc = 0;
911
912 /* Frame dimensions in macroblocks */
913 ev->frame_mb_x = (avctx->width + APV_MB_WIDTH - 1) / APV_MB_WIDTH;
914 ev->frame_mb_y = (avctx->height + APV_MB_HEIGHT - 1) / APV_MB_HEIGHT;
915
916 /* The 20x20 tile grid cap is structural (fixed-size arrays everywhere);
917 * the spec additionally demands tiles of at least 16x8 MBs. Each
918 * tile-component maps to one entropy workgroup, one invocation per
919 * transform block. */
920 int grid_tw = (ev->frame_mb_x + APV_MAX_TILE_COLS - 1) / APV_MAX_TILE_COLS;
921 int grid_th = (ev->frame_mb_y + APV_MAX_TILE_ROWS - 1) / APV_MAX_TILE_ROWS;
922 int min_tw = FFMAX(APV_MIN_TILE_WIDTH_IN_MBS, grid_tw);
923 int min_th = FFMAX(APV_MIN_TILE_HEIGHT_IN_MBS, grid_th);
924
925 /* tile_w/tile_h pick the tile size in MBs; 0 selects the spec minimum.
926 * An explicit request below the spec minimum is honoured down to the
927 * grid cap -- non-conformant, but more tiles mean shorter (serial)
928 * entropy streams, which is the decode speed lever. */
929 ev->tile_mb_w = ev->tile_w_mbs_opt > 0 ? ev->tile_w_mbs_opt : min_tw;
930 ev->tile_mb_h = ev->tile_h_mbs_opt > 0 ? ev->tile_h_mbs_opt : min_th;
931 ev->tile_mb_w = FFMIN(FFMAX(ev->tile_mb_w, grid_tw), ev->frame_mb_x);
932 ev->tile_mb_h = FFMIN(FFMAX(ev->tile_mb_h, grid_th), ev->frame_mb_y);
935 av_log(avctx, AV_LOG_WARNING,
936 "Tile size %dx%d MBs is below the spec minimum of %dx%d: "
937 "NON-CONFORMANT bitstream, most decoders will reject it.\n",
938 ev->tile_mb_w, ev->tile_mb_h,
940
941 /* Left to default, grow the tile toward 1024 transform blocks (the
942 * entropy workgroup ceiling) while it still divides the frame. Bigger
943 * tiles mean fewer tile-components, which the compaction pass strongly
944 * prefers -- it is the dominant win for throughput. */
945 if (!ev->tile_w_mbs_opt && !ev->tile_h_mbs_opt) {
946 while (ev->tile_mb_w * 2 <= ev->frame_mb_x &&
947 ev->frame_mb_x % (ev->tile_mb_w * 2) == 0 &&
948 (ev->tile_mb_w * 2) * ev->tile_mb_h * ev->blocks_per_mb <= 1024)
949 ev->tile_mb_w *= 2;
950 while (ev->tile_mb_h * 2 <= ev->frame_mb_y &&
951 ev->frame_mb_y % (ev->tile_mb_h * 2) == 0 &&
952 ev->tile_mb_w * (ev->tile_mb_h * 2) * ev->blocks_per_mb <= 1024)
953 ev->tile_mb_h *= 2;
954 }
955
956 /* Ceil division: the rightmost column / bottom row of tiles take the
957 * remainder MBs (spec-legal; the tile grid is closed at the frame edge,
958 * so those tiles may be smaller than the signalled tile size). */
959 ev->tile_cols = (ev->frame_mb_x + ev->tile_mb_w - 1) / ev->tile_mb_w;
960 ev->tile_rows = (ev->frame_mb_y + ev->tile_mb_h - 1) / ev->tile_mb_h;
961 ev->tile_count = ev->tile_cols * ev->tile_rows;
962
963 if (ev->tile_count > APV_MAX_TILE_COUNT) {
964 av_log(avctx, AV_LOG_ERROR, "Too many tiles (%d).\n", ev->tile_count);
965 return AVERROR(EINVAL);
966 }
967
968 /* The entropy shader runs one invocation per block in a tile-component
969 * and its shared buffers are sized for 1024. */
970 if (ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb > 1024) {
971 av_log(avctx, AV_LOG_ERROR,
972 "Tile-component has too many transform blocks (%d > 1024).\n",
973 ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb);
975 }
976
977 /* qp_chroma left at 0 means "use the luma QP". */
978 if (ev->qp_c == 0)
979 ev->qp_c = ev->qp_y;
980
981 /* Validate QP range */
982 int max_qp = 3 + ev->bit_depth * 6;
983 if (ev->qp_y < 0 || ev->qp_y > max_qp || ev->qp_c < 0 || ev->qp_c > max_qp) {
984 av_log(avctx, AV_LOG_ERROR,
985 "QP out of range [0, %d]: qp_y=%d, qp_c=%d.\n",
986 max_qp, ev->qp_y, ev->qp_c);
987 return AVERROR(EINVAL);
988 }
989
990 /* Buffer sizing */
991 size_t blocks_per_tile = (size_t)ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb;
992 ev->coeffs_size = (size_t)ev->tile_count * ev->num_comp *
993 blocks_per_tile * APV_BLK_COEFFS * sizeof(int16_t);
994
995 /* Worst-case per-tile-component bytestream: each coefficient at most ~32 bits.
996 * Round up generously. */
997 ev->slot_size = blocks_per_tile * APV_BLK_COEFFS * 8;
998 ev->slot_size = FFALIGN(ev->slot_size, 64);
999 ev->bytestream_size = (size_t)ev->tile_count * ev->num_comp * ev->slot_size;
1000 ev->sizes_size = (size_t)ev->tile_count * ev->num_comp * sizeof(uint32_t);
1001
1002 av_log(avctx, AV_LOG_VERBOSE,
1003 "APV Vulkan encoder: %dx%d, %d tiles (%dx%d MBs each), "
1004 "qp_y=%d qp_c=%d, coeffs=%zu KiB, bytestream=%zu KiB\n",
1005 avctx->width, avctx->height, ev->tile_count,
1006 ev->tile_mb_w, ev->tile_mb_h, ev->qp_y, ev->qp_c,
1007 ev->coeffs_size / 1024, ev->bytestream_size / 1024);
1008
1009 ev->headers_only = !!getenv("APV_VULKAN_HEADERS_ONLY");
1010 ev->skip_entropy = !!getenv("APV_VULKAN_SKIP_ENTROPY");
1011 if (ev->skip_entropy)
1012 ev->headers_only = 1; /* the bitstream is never produced */
1013 if (ev->headers_only)
1014 av_log(avctx, AV_LOG_WARNING,
1015 "APV_VULKAN_HEADERS_ONLY set: tiles will not be downloaded "
1016 "or assembled; output packets contain headers only.\n");
1017 if (ev->skip_entropy)
1018 av_log(avctx, AV_LOG_WARNING,
1019 "APV_VULKAN_SKIP_ENTROPY set: entropy dispatch skipped "
1020 "(DCT-only benchmark mode).\n");
1021
1022 /* Init Vulkan */
1023 err = ff_vk_init(&ev->s, avctx, NULL, avctx->hw_frames_ctx);
1024 if (err < 0)
1025 return err;
1026
1027 ev->qf = ff_vk_qf_find(&ev->s, VK_QUEUE_COMPUTE_BIT, 0);
1028 if (!ev->qf) {
1029 av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
1030 return AVERROR(ENOTSUP);
1031 }
1032
1033 err = ff_vk_exec_pool_init(&ev->s, ev->qf, &ev->exec_pool,
1034 ev->async_depth, 0, 0, 0, NULL);
1035 if (err < 0)
1036 return err;
1037
1038 /* Init CBS for assembling output */
1039 err = ff_cbs_init(&ev->cbc, AV_CODEC_ID_APV, avctx);
1040 if (err < 0)
1041 return err;
1042
1043 /* Shaders */
1044 err = init_dct_shader(avctx);
1045 if (err < 0)
1046 return err;
1047 err = init_entropy_shader(avctx, ev->blocks_per_mb, &ev->shd_entropy[0]);
1048 if (err < 0)
1049 return err;
1051 &ev->shd_entropy[1]);
1052 if (err < 0)
1053 return err;
1054 err = init_compact_shader(avctx);
1055 if (err < 0)
1056 return err;
1057
1058 /* The DCT/quantize shader's push constants never change frame to frame;
1059 * build them once. */
1060 build_dct_push_const(avctx);
1061
1062 ev->frame = av_frame_alloc();
1063 if (!ev->frame)
1064 return AVERROR(ENOMEM);
1065
1066 /* Async data pool */
1068 ev->exec_ctx_info = av_calloc(ev->async_depth, sizeof(*ev->exec_ctx_info));
1069 if (!ev->exec_ctx_info)
1070 return AVERROR(ENOMEM);
1071 for (int i = 0; i < ev->async_depth; i++)
1073
1074 return 0;
1075}
1076
1077#define OFFSET(x) offsetof(VulkanEncodeAPVContext, x)
1078#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1080 { "qp", "Quantization parameter (luma)", OFFSET(qp_y),
1081 AV_OPT_TYPE_INT, { .i64 = 22 }, 0, 255, VE },
1082 { "qp_chroma", "Chroma quantization parameter (0 = same as luma qp)", OFFSET(qp_c),
1083 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 255, VE },
1084 { "qmatrix", "Quantization matrix", OFFSET(qmatrix),
1085 AV_OPT_TYPE_INT, { .i64 = APV_QMATRIX_HEVC }, 0, 1, VE, "qmatrix" },
1086 { "flat", "Uniform matrix, all 16 (APV spec default)", 0,
1087 AV_OPT_TYPE_CONST, { .i64 = APV_QMATRIX_FLAT }, 0, 0, VE, "qmatrix" },
1088 { "hevc", "HEVC default intra scaling list (mild perceptual shaping)", 0,
1089 AV_OPT_TYPE_CONST, { .i64 = APV_QMATRIX_HEVC }, 0, 0, VE, "qmatrix" },
1090 /* The minimum legal tile is 16x8 MBs; the maxima are this encoder's
1091 * ceiling of 1024 transform blocks per tile-component (256 MBs): with
1092 * the other dimension at its minimum, width <= 32 and height <= 16. A
1093 * value of 0 is the sentinel for the adaptive per-frame default. */
1094 { "tile_width", "Tile width in macroblocks (0 = adaptive, auto-sized per frame)", OFFSET(tile_w_mbs_opt),
1095 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 32, VE },
1096 { "tile_height", "Tile height in macroblocks (0 = adaptive, auto-sized per frame)", OFFSET(tile_h_mbs_opt),
1097 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 16, VE },
1098 { "async_depth", "Internal parallelization depth", OFFSET(async_depth),
1099 AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, VE },
1100 { NULL }
1101};
1102
1104 { "g", "1" },
1105 { NULL },
1106};
1107
1109 .class_name = "apv_vulkan",
1110 .item_name = av_default_item_name,
1111 .option = vulkan_encode_apv_options,
1112 .version = LIBAVUTIL_VERSION_INT,
1113};
1114
1116 HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
1117 NULL,
1118};
1119
1121 .p.name = "apv_vulkan",
1122 CODEC_LONG_NAME("Advanced Professional Video (Vulkan)"),
1123 .p.type = AVMEDIA_TYPE_VIDEO,
1124 .p.id = AV_CODEC_ID_APV,
1125 .priv_data_size = sizeof(VulkanEncodeAPVContext),
1128 .close = &vulkan_encode_apv_close,
1129 .p.priv_class = &vulkan_encode_apv_class,
1130 .p.capabilities = AV_CODEC_CAP_DELAY |
1136 .defaults = vulkan_encode_apv_defaults,
1138 .hw_configs = vulkan_encode_apv_hw_configs,
1139 .p.wrapper_name = "vulkan",
1140};
static double fact(double i)
Definition af_aiir.c:935
const FFCodec ff_apv_vulkan_encoder
#define VE
Definition amfenc_av1.c:30
const unsigned int ff_apv_encode_dct_comp_spv_len
static int build_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned char ff_apv_encode_tiles_comp_spv_data[]
static int vulkan_encode_apv_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static const uint8_t apv_qmat_hevc_intra[64]
static av_cold int vulkan_encode_apv_init(AVCodecContext *avctx)
static const AVCodecHWConfigInternal *const vulkan_encode_apv_hw_configs[]
const unsigned char ff_apv_encode_dct_comp_spv_data[]
static const uint8_t apv_level_scale[6]
static int init_dct_shader(AVCodecContext *avctx)
static int init_entropy_shader(AVCodecContext *avctx, int blocks_per_mb, FFVulkanShader *shd)
@ APV_QMATRIX_FLAT
@ APV_QMATRIX_HEVC
static const AVClass vulkan_encode_apv_class
#define APV_DEFAULT_QMAT
static av_cold int vulkan_encode_apv_close(AVCodecContext *avctx)
static void build_dct_push_const(AVCodecContext *avctx)
static const AVOption vulkan_encode_apv_options[]
static const FFCodecDefault vulkan_encode_apv_defaults[]
static int profile_idc_from_pix_fmt(enum AVPixelFormat sw_fmt)
#define OFFSET(x)
static int chroma_format_from_pix_fmt(enum AVPixelFormat sw_fmt)
static int submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame)
static int init_compact_shader(AVCodecContext *avctx)
#define APV_MAX_NUM_COMP
const unsigned char ff_seg_gather_comp_spv_data[]
const unsigned int ff_seg_gather_comp_spv_len
static int apv_qmatrix_value(int qmatrix, int i)
const unsigned int ff_apv_encode_tiles_comp_spv_len
Libavcodec external API header.
static int FUNC tile(CodedBitstreamContext *ctx, RWContext *rw, APVRawTile *current, int tile_idx, uint32_t tile_size)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_CAP_EOF_FLUSH
The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it only wants to be flushe...
#define CODEC_PIXFMTS(...)
#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...
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
Definition encode.c:218
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
#define fail
Definition test.h:479
@ 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_ENCODER_FLUSH
This encoder can be flushed using avcodec_flush_buffers().
Definition codec.h:154
#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
#define AV_CODEC_FLAG_COPY_OPAQUE
Definition avcodec.h:279
@ AV_CODEC_ID_APV
Definition codec_id.h:323
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
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_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#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
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
static const int sizes[][2]
Definition img2dec.c:62
#define r
Definition input.c:42
static const int level_scale[2][6]
Definition intra.c:336
@ APV_PBU_PRIMARY_FRAME
Definition apv.h:27
@ APV_CHROMA_FORMAT_422
Definition apv.h:48
@ APV_CHROMA_FORMAT_400
Definition apv.h:47
@ APV_CHROMA_FORMAT_4444
Definition apv.h:50
@ APV_CHROMA_FORMAT_444
Definition apv.h:49
@ APV_MB_HEIGHT
Definition apv.h:41
@ APV_MB_WIDTH
Definition apv.h:40
@ APV_MIN_TILE_WIDTH_IN_MBS
Definition apv.h:73
@ APV_MAX_TILE_COUNT
Definition apv.h:77
@ APV_MAX_TILE_COLS
Definition apv.h:75
@ APV_MIN_TILE_HEIGHT_IN_MBS
Definition apv.h:74
@ APV_MAX_TILE_ROWS
Definition apv.h:76
@ APV_PROFILE_4444_12
Definition apv.h:67
@ APV_PROFILE_444_10
Definition apv.h:64
@ APV_PROFILE_400_10
Definition apv.h:68
@ APV_PROFILE_422_10
Definition apv.h:62
@ APV_PROFILE_422_12
Definition apv.h:63
@ APV_PROFILE_4444_10
Definition apv.h:66
@ APV_PROFILE_444_12
Definition apv.h:65
@ APV_BLK_COEFFS
Definition apv.h:55
common internal api header.
#define av_cold
Definition attributes.h:117
void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, AVFrame *f, VkImageView *views, int set, int binding, VkImageLayout layout, VkSampler sampler)
Update a descriptor in a buffer with an image array.
Definition vulkan.c:2712
int ff_vk_shader_load(FFVulkanShader *shd, VkPipelineStageFlags stage, VkSpecializationInfo *spec, uint32_t wg_size[3], uint32_t required_subgroup_size)
Initialize a shader object.
Definition vulkan.c:2240
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
Definition vulkan.c:2543
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:331
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
Definition vulkan.c:395
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:645
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1613
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2808
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
Definition vulkan.c:2824
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage, VkAccessFlagBits2 new_access, VkImageLayout new_layout, uint32_t new_qf)
Definition vulkan.c:2197
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, VkImageView views[AV_NUM_DATA_POINTERS], AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
Create an imageview and add it as a dependency to an execution.
Definition vulkan.c:2128
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2784
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2577
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:622
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:969
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2761
void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Definition vulkan.c:786
int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int elem, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len, VkFormat fmt)
Update a descriptor in a buffer with a buffer.
Definition vulkan.c:2725
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:316
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:779
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition vulkan.c:1426
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:763
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, const char *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
Definition vulkan.c:2437
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Update push constant in a shader.
Definition vulkan.c:2751
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
APVRawTileInfo tile_info
Definition cbs_apv.h:80
uint8_t color_primaries
Definition cbs_apv.h:72
uint8_t color_description_present_flag
Definition cbs_apv.h:71
APVRawFrameInfo frame_info
Definition cbs_apv.h:68
APVRawQuantizationMatrix quantization_matrix
Definition cbs_apv.h:78
uint8_t full_range_flag
Definition cbs_apv.h:75
uint8_t matrix_coefficients
Definition cbs_apv.h:74
uint8_t transfer_characteristics
Definition cbs_apv.h:73
uint8_t use_q_matrix
Definition cbs_apv.h:77
uint8_t level_idc
Definition cbs_apv.h:45
uint32_t frame_width
Definition cbs_apv.h:48
uint8_t band_idc
Definition cbs_apv.h:46
uint8_t bit_depth_minus8
Definition cbs_apv.h:51
uint8_t profile_idc
Definition cbs_apv.h:44
uint32_t frame_height
Definition cbs_apv.h:49
uint8_t chroma_format_idc
Definition cbs_apv.h:50
uint8_t capture_time_distance
Definition cbs_apv.h:52
APVRawFrameHeader frame_header
Definition cbs_apv.h:103
APVRawTile tile[APV_MAX_TILE_COUNT]
Definition cbs_apv.h:105
APVRawPBUHeader pbu_header
Definition cbs_apv.h:102
uint32_t tile_size[APV_MAX_TILE_COUNT]
Definition cbs_apv.h:104
uint8_t pbu_type
Definition cbs_apv.h:34
uint16_t group_id
Definition cbs_apv.h:35
uint8_t q_matrix[APV_MAX_NUM_COMP][APV_TR_SIZE][APV_TR_SIZE]
Definition cbs_apv.h:57
uint32_t tile_width_in_mbs
Definition cbs_apv.h:61
uint32_t tile_height_in_mbs
Definition cbs_apv.h:62
uint8_t tile_size_present_in_fh_flag
Definition cbs_apv.h:63
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
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
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
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
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
Definition refstruct.c:183
VkDevice act_dev
Active device.
Context structure for coded bitstream operations.
Definition cbs.h:226
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
VkDeviceAddress compacted
VkDeviceAddress sparse
float qf[APV_MAX_NUM_COMP]
uint8_t qmat[64]
VkDeviceAddress bytestream
VkDeviceAddress address
Definition vulkan.h:99
size_t size
Definition vulkan.h:98
VkMemoryPropertyFlagBits flags
Definition vulkan.h:97
VkDeviceMemory mem
Definition vulkan.h:96
uint8_t * mapped_mem
Definition vulkan.h:103
void * opaque
Definition vulkan.h:154
int had_submission
Definition vulkan.h:134
VkCommandBuffer buf
Definition vulkan.h:142
FFVkExecContext * contexts
Definition vulkan.h:273
int pool_size
Definition vulkan.h:278
AVVulkanDeviceContext * hwctx
Definition vulkan.h:339
FFVulkanFunctions vkfn
Definition vulkan.h:298
CodedBitstreamContext * cbc
AVRefStructPool * coeffs_pool
AVRefStructPool * gathered_pool
CodedBitstreamFragment au
AVVulkanDeviceQueueFamily * qf
AVRefStructPool * sizes_pool
FFVulkanShader shd_entropy[2]
AVRefStructPool * compacted_pool
enum AVPixelFormat sw_format
VulkanEncodeAPVFrameData * exec_ctx_info
AVRefStructPool * bytestream_pool
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define NONE
Definition vf_drawvg.c:262
static double c[64]
#define ff_vk_buf_barrier(dst, vkb, s_stage, s_access, s_access2, d_stage, d_access, d_access2, offs, bsz)
Definition vulkan.h:575
@ FF_VK_REP_INT
Definition vulkan.h:443
#define RET(x)
Definition vulkan.h:37
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition vulkan.h:55
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition vulkan.h:45