FFmpeg
Loading...
Searching...
No Matches
proresenc_kostya_vulkan.c
Go to the documentation of this file.
1/*
2 * Apple ProRes encoder
3 *
4 * Copyright (c) 2011 Anatoliy Wasserman
5 * Copyright (c) 2012 Konstantin Shishkov
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "libavutil/avassert.h"
25#include "libavutil/buffer.h"
26#include "libavutil/macros.h"
27#include "libavutil/mem.h"
29#include "libavutil/opt.h"
30#include "libavutil/pixdesc.h"
33#include "libavutil/vulkan.h"
34#include "avcodec.h"
35#include "codec.h"
36#include "codec_internal.h"
37#include "encode.h"
38#include "packet.h"
39#include "put_bits.h"
40#include "profiles.h"
41#include "bytestream.h"
42#include "proresdata.h"
44#include "hwconfig.h"
45
46#define DCTSIZE 8
47
48typedef struct ProresDataTables {
49 int16_t qmat[128][64];
50 int16_t qmat_chroma[128][64];
52
58
59typedef struct EncodeSliceInfo {
60 VkDeviceAddress bytestream;
61 VkDeviceAddress slice_sizes;
62 uint32_t slot_size;
64
65typedef struct SegGatherPushData {
66 VkDeviceAddress sparse;
67 VkDeviceAddress compacted;
68 uint32_t slot_size;
70
71typedef struct SliceData {
72 uint32_t mbs_per_slice;
74} SliceData;
75
85
106
141
142extern const unsigned char ff_prores_ks_alpha_data_comp_spv_data[];
143extern const unsigned int ff_prores_ks_alpha_data_comp_spv_len;
144
145extern const unsigned char ff_seg_gather_comp_spv_data[];
146extern const unsigned int ff_seg_gather_comp_spv_len;
147
148extern const unsigned char ff_prores_ks_slice_data_comp_spv_data[];
149extern const unsigned int ff_prores_ks_slice_data_comp_spv_len;
150
151extern const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[];
152extern const unsigned int ff_prores_ks_estimate_slice_comp_spv_len;
153
154extern const unsigned char ff_prores_ks_trellis_node_comp_spv_data[];
155extern const unsigned int ff_prores_ks_trellis_node_comp_spv_len;
156
157extern const unsigned char ff_prores_ks_encode_slice_comp_spv_data[];
158extern const unsigned int ff_prores_ks_encode_slice_comp_spv_len;
159
160static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
161{
162 int err = 0;
163 FFVulkanContext *vkctx = &pv->vkctx;
165
166 SPEC_LIST_CREATE(sl, 5, 5 * sizeof(uint32_t))
167 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
168 SPEC_LIST_ADD(sl, 1, 32, blocks_per_mb);
169 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
170 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.pictures_per_frame);
171 SPEC_LIST_ADD(sl, 16, 32, blocks_per_mb * pv->ctx.mbs_per_slice); /* nb_blocks */
172
173 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
174 (uint32_t []) { DCTSIZE, blocks_per_mb, pv->ctx.mbs_per_slice }, 0);
175
177 {
178 .name = "SliceBuffer",
179 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
180 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
181 },
182 {
183 .name = "planes",
184 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
185 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
186 .elems = av_pix_fmt_count_planes(vkctx->frames->sw_format),
187 },
188 };
189 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
190
191 ff_vk_shader_add_push_const(shd, 0, sizeof(SliceDataInfo), VK_SHADER_STAGE_COMPUTE_BIT);
192
193 RET(ff_vk_shader_link(vkctx, shd,
196
197 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
198
199fail:
200 return err;
201}
202
204{
205 int err = 0;
206 FFVulkanContext *vkctx = &pv->vkctx;
208
209 SPEC_LIST_CREATE(sl, 4, 4 * sizeof(uint32_t))
210 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.alpha_bits);
211 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.slices_width);
212 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
213 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.mbs_per_slice);
214
215 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
216 (uint32_t []) { 16, 16, 1 }, 0);
217
219 {
220 .name = "SliceBuffer",
221 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
222 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
223 },
224 {
225 .name = "plane",
226 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
227 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
228 },
229 };
230 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
231
232 RET(ff_vk_shader_link(vkctx, shd,
235
236 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
237
238fail:
239 return err;
240}
241
243{
244 int err = 0;
245 FFVulkanContext *vkctx = &pv->vkctx;
247 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
248 int dim_x = pv->ctx.alpha_bits ? subgroup_size : (subgroup_size / 3) * 3;
249
250 SPEC_LIST_CREATE(sl, 8, 8 * sizeof(uint32_t))
251 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
252 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
253 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
254 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
255 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
256 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->min_quant);
257 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->max_quant);
258 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
259
260 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
261 (uint32_t []) { dim_x, 1, 1 }, 0);
262
264 {
265 .name = "SliceBuffer",
266 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
267 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
268 },
269 {
270 .name = "SliceScores",
271 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
272 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
273 },
274 {
275 .name = "ProresDataTables",
276 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
277 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
278 },
279 };
280 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
281
282 RET(ff_vk_shader_link(vkctx, shd,
285 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
286
287fail:
288 return err;
289}
290
292{
293 int err = 0;
294 FFVulkanContext *vkctx = &pv->vkctx;
296 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
297 int num_subgroups = FFALIGN(pv->ctx.mb_height, subgroup_size) / subgroup_size;
298
299 SPEC_LIST_CREATE(sl, 8, 8 * sizeof(uint32_t))
300 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.slices_width);
301 SPEC_LIST_ADD(sl, 1, 32, num_subgroups);
302 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.num_planes);
303 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.force_quant);
304 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.profile_info->min_quant);
305 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.profile_info->max_quant);
306 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.mbs_per_slice);
307 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
308
309 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
310 (uint32_t []) { pv->ctx.mb_height, 1, 1 }, 0);
311
313 {
314 .name = "FrameSize",
315 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
316 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
317 },
318 {
319 .name = "SliceScores",
320 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
321 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
322 },
323 };
324 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
325
326 RET(ff_vk_shader_link(vkctx, shd,
329
330 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
331
332fail:
333 return err;
334}
335
337{
338 int err = 0;
339 FFVulkanContext *vkctx = &pv->vkctx;
341
342 SPEC_LIST_CREATE(sl, 6, 6 * sizeof(uint32_t))
343 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
344 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
345 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
346 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
347 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
349
350 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
351 (uint32_t []) { 64, 1, 1 }, 0);
352
354 {
355 .name = "SliceBuffer",
356 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
357 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
358 },
359 {
360 .name = "SliceScores",
361 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
362 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
363 },
364 {
365 .name = "ProresDataTables",
366 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
367 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
368 },
369 };
370 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
371
372 ff_vk_shader_add_push_const(shd, 0, sizeof(EncodeSliceInfo), VK_SHADER_STAGE_COMPUTE_BIT);
373
374 RET(ff_vk_shader_link(vkctx, shd,
377
378 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
379
380fail:
381 return err;
382}
383
385{
386 int err = 0;
387 FFVulkanContext *vkctx = &pv->vkctx;
389
390 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
391 (uint32_t []) { 256, 1, 1 }, 0);
392
394 {
395 .name = "sizes_buf",
396 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
397 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
398 },
399 };
400 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 1, 0);
401
403 VK_SHADER_STAGE_COMPUTE_BIT);
404
405 RET(ff_vk_shader_link(vkctx, shd,
408
409 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
410
411fail:
412 return err;
413}
414
416 AVFrame *frame, int picture_idx)
417{
418 ProresVulkanContext *pv = avctx->priv_data;
419 ProresContext *ctx = &pv->ctx;
421 FFVulkanContext *vkctx = &pv->vkctx;
422 FFVulkanFunctions *vk = &vkctx->vkfn;
423 int err = 0, nb_img_bar = 0, i, is_chroma;
424 int min_quant = ctx->profile_info->min_quant;
425 int max_quant = ctx->profile_info->max_quant;
426 int subgroup_size = vkctx->subgroup_props.maxSubgroupSize;
427 int estimate_dim_x = ctx->alpha_bits ? subgroup_size : (subgroup_size / 3) * 3;
429 VkImageView views[AV_NUM_DATA_POINTERS];
430 VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
431 FFVkBuffer *pkt_vk_buf, *slice_data_buf, *slice_score_buf, *frame_size_buf;
432 SliceDataInfo slice_data_info;
433 EncodeSliceInfo encode_info;
434 FFVulkanShader *shd;
435
436 /* Start recording */
437 ff_vk_exec_start(vkctx, exec);
438
439 /* Sparse slice output: one fixed-stride, device-local slot per slice */
440 RET(ff_vk_get_pooled_buffer(vkctx, &pv->pkt_buf_pool, &pd->out_data_ref[picture_idx],
441 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
442 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
443 ctx->slices_per_picture * pv->slice_slot_size,
444 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
445 pkt_vk_buf = pd->out_data_ref[picture_idx];
446 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->out_data_ref[picture_idx]);
447
448 /* Per-slice sizes: read by the gather pass, and by the CPU to write the
449 * seek table. */
451 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
452 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
453 ctx->slices_per_picture * sizeof(uint32_t),
454 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
455 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
456 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
457 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_sizes_ref[picture_idx]);
458
459 /* Picture 0 is gathered directly into the packet buffer at its static
460 * offset; picture 1's offset depends on picture 0's encoded size, so it
461 * is gathered to a scratch buffer and moved into place by the CPU. */
462 RET(ff_vk_get_pooled_buffer(vkctx, &pv->gathered_buf_pool, &pd->gathered_ref[picture_idx],
463 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
464 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
465 picture_idx == 0 ? ctx->frame_size_upper_bound + FF_INPUT_BUFFER_MIN_SIZE
466 : ctx->slices_per_picture * pv->slice_slot_size,
467 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
468 vkctx->host_cached_flag));
469 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->gathered_ref[picture_idx]);
470
471 /* Allocate buffer for writing slice data */
472 RET(ff_vk_get_pooled_buffer(vkctx, &pv->slice_data_buf_pool, &pd->slice_data_ref[picture_idx],
473 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
474 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
475 ctx->slices_per_picture * sizeof(SliceData),
476 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
477 slice_data_buf = pd->slice_data_ref[picture_idx];
478 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_data_ref[picture_idx]);
479
480 /* Allocate buffer for writing slice scores */
482 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
483 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
484 ctx->slices_per_picture * sizeof(SliceScore),
485 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
486 slice_score_buf = pd->slice_score_ref[picture_idx];
487 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_score_ref[picture_idx]);
488
489 /* Allocate buffer for writing frame size */
490 RET(ff_vk_get_pooled_buffer(vkctx, &pv->frame_size_buf_pool, &pd->frame_size_ref[picture_idx],
491 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
492 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
493 sizeof(int),
494 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
495 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
496 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
497 frame_size_buf = pd->frame_size_ref[picture_idx];
498 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->frame_size_ref[picture_idx]);
499
500 /* Generate barriers and image views for frame images. */
502 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
503 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
504 RET(ff_vk_create_imageviews(vkctx, exec, views, frame, FF_VK_REP_INT));
505 ff_vk_frame_barrier(vkctx, exec, frame, img_bar, &nb_img_bar,
506 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
507 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
508 VK_ACCESS_SHADER_READ_BIT,
509 VK_IMAGE_LAYOUT_GENERAL,
510 VK_QUEUE_FAMILY_IGNORED);
511
512 /* Submit the image barriers. */
513 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
514 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
515 .pImageMemoryBarriers = img_bar,
516 .imageMemoryBarrierCount = nb_img_bar,
517 });
518
519 /* Apply FDCT on input image data for future passes */
520 slice_data_info = (SliceDataInfo) {
521 .line_add = ctx->pictures_per_frame == 1 ? 0 : picture_idx ^ !(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST),
522 };
523 for (i = 0; i < ctx->num_planes; i++) {
524 is_chroma = (i == 1 || i == 2);
525 shd = &pv->slice_data_shd[!is_chroma || ctx->chroma_factor == CFACTOR_Y444];
526 if (i < 3) {
527 slice_data_info.plane = i;
528 slice_data_info.bits_per_sample = desc->comp[i].depth;
529 ff_vk_shader_update_desc_buffer(vkctx, exec, shd, 0, 0, 0,
530 slice_data_buf, 0, slice_data_buf->size,
531 VK_FORMAT_UNDEFINED);
532 ff_vk_shader_update_img_array(vkctx, exec, shd, frame, views, 0, 1,
533 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
534 ff_vk_exec_bind_shader(vkctx, exec, shd);
535 ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
536 0, sizeof(SliceDataInfo), &slice_data_info);
537 vk->CmdDispatch(exec->buf, ctx->slices_width, ctx->mb_height, 1);
538 } else {
539 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->alpha_data_shd, 0, 0, 0,
540 slice_data_buf, 0, slice_data_buf->size,
541 VK_FORMAT_UNDEFINED);
542 ff_vk_shader_update_img(vkctx, exec, &pv->alpha_data_shd, 0, 1, 0, views[3],
543 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
544 ff_vk_exec_bind_shader(vkctx, exec, &pv->alpha_data_shd);
545 vk->CmdDispatch(exec->buf, ctx->mb_width, ctx->mb_height, 1);
546 }
547 }
548
549 /* Wait for writes to slice buffer. */
550 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
551 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
552 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
553 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
554 .pNext = NULL,
555 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
556 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
557 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
558 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
559 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
560 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
561 .buffer = slice_data_buf->buf,
562 .offset = 0,
563 .size = slice_data_buf->size,
564 },
565 .bufferMemoryBarrierCount = 1,
566 });
567
568 /* Estimate slice bits and error for each quant */
569 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 0, 0,
570 slice_data_buf, 0, slice_data_buf->size,
571 VK_FORMAT_UNDEFINED);
572 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 1, 0,
573 slice_score_buf, 0, slice_score_buf->size,
574 VK_FORMAT_UNDEFINED);
575 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 2, 0,
576 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
577 VK_FORMAT_UNDEFINED);
578 ff_vk_exec_bind_shader(vkctx, exec, &pv->estimate_slice_shd);
579 vk->CmdDispatch(exec->buf, (ctx->slices_per_picture * ctx->num_planes + estimate_dim_x - 1) / estimate_dim_x,
580 ctx->force_quant ? 1 : (max_quant - min_quant + 1), 1);
581
582 /* Wait for writes to score buffer. */
583 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
584 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
585 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
586 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
587 .pNext = NULL,
588 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
589 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
590 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
591 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
592 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
593 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
594 .buffer = slice_score_buf->buf,
595 .offset = 0,
596 .size = slice_score_buf->size,
597 },
598 .bufferMemoryBarrierCount = 1,
599 });
600
601 /* Compute optimal quant value for each slice */
602 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->trellis_node_shd, 0, 0, 0,
603 frame_size_buf, 0, frame_size_buf->size,
604 VK_FORMAT_UNDEFINED);
605 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->trellis_node_shd, 0, 1, 0,
606 slice_score_buf, 0, slice_score_buf->size,
607 VK_FORMAT_UNDEFINED);
608 ff_vk_exec_bind_shader(vkctx, exec, &pv->trellis_node_shd);
609 vk->CmdDispatch(exec->buf, 1, 1, 1);
610
611 /* Wait for writes to quant buffer. */
612 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
613 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
614 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
615 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
616 .pNext = NULL,
617 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
618 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
619 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
620 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
621 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
622 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
623 .buffer = frame_size_buf->buf,
624 .offset = 0,
625 .size = frame_size_buf->size,
626 },
627 .bufferMemoryBarrierCount = 1,
628 });
629
630 /* Encode slices. */
631 encode_info = (EncodeSliceInfo) {
632 .bytestream = pkt_vk_buf->address,
633 .slice_sizes = pd->slice_sizes_ref[picture_idx]->address,
634 .slot_size = pv->slice_slot_size,
635 };
636 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 0, 0,
637 slice_data_buf, 0, slice_data_buf->size,
638 VK_FORMAT_UNDEFINED);
639 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 1, 0,
640 slice_score_buf, 0, slice_score_buf->size,
641 VK_FORMAT_UNDEFINED);
642 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 2, 0,
643 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
644 VK_FORMAT_UNDEFINED);
645 ff_vk_exec_bind_shader(vkctx, exec, &pv->encode_slice_shd);
646 ff_vk_shader_update_push_const(vkctx, exec, &pv->encode_slice_shd,
647 VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(encode_info), &encode_info);
648 vk->CmdDispatch(exec->buf, FFALIGN(ctx->slices_per_picture, 64) / 64,
649 ctx->num_planes, 1);
650
651 /* Gather the sparse slots into the contiguous bitstream, in the same
652 * submission. */
653 VkBufferMemoryBarrier2 gather_bar[2] = {
654 {
655 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
656 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
657 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
658 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
659 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
660 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
661 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
662 .buffer = pkt_vk_buf->buf,
663 .offset = 0,
664 .size = pkt_vk_buf->size,
665 }, {
666 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
667 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
668 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
669 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
670 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
671 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
672 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
673 .buffer = pd->slice_sizes_ref[picture_idx]->buf,
674 .offset = 0,
675 .size = pd->slice_sizes_ref[picture_idx]->size,
676 },
677 };
678 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
679 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
680 .pBufferMemoryBarriers = gather_bar,
681 .bufferMemoryBarrierCount = 2,
682 });
683
684 SegGatherPushData gather_pd = {
685 .sparse = pkt_vk_buf->address,
686 .compacted = pd->gathered_ref[picture_idx]->address +
687 (picture_idx == 0 ? pv->payload_off : 0),
688 .slot_size = pv->slice_slot_size,
689 };
690 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->gather_shd, 0, 0, 0,
691 pd->slice_sizes_ref[picture_idx],
692 0, ctx->slices_per_picture * sizeof(uint32_t),
693 VK_FORMAT_UNDEFINED);
694 ff_vk_exec_bind_shader(vkctx, exec, &pv->gather_shd);
695 ff_vk_shader_update_push_const(vkctx, exec, &pv->gather_shd,
696 VK_SHADER_STAGE_COMPUTE_BIT,
697 0, sizeof(gather_pd), &gather_pd);
698 vk->CmdDispatch(exec->buf, ctx->slices_per_picture, 1, 1);
699
700fail:
701 return err;
702}
703
705 uint8_t **orig_buf, int flags,
707 enum AVColorTransferCharacteristic color_trc,
708 enum AVColorSpace colorspace)
709{
710 uint8_t *buf, *tmp;
711 uint8_t frame_flags;
712
713 // frame atom
714 *orig_buf += 4; // frame size
715 bytestream_put_be32 (orig_buf, FRAME_ID); // frame container ID
716 buf = *orig_buf;
717
718 // frame header
719 tmp = buf;
720 buf += 2; // frame header size will be stored here
721 bytestream_put_be16 (&buf, ctx->chroma_factor != CFACTOR_Y422 || ctx->alpha_bits ? 1 : 0);
722 bytestream_put_buffer(&buf, (uint8_t*)ctx->vendor, 4);
723 bytestream_put_be16 (&buf, avctx->width);
724 bytestream_put_be16 (&buf, avctx->height);
725
726 frame_flags = ctx->chroma_factor << 6;
728 frame_flags |= (flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x04 : 0x08;
729 bytestream_put_byte (&buf, frame_flags);
730
731 bytestream_put_byte (&buf, 0); // reserved
732 bytestream_put_byte (&buf, color_primaries);
733 bytestream_put_byte (&buf, color_trc);
734 bytestream_put_byte (&buf, colorspace);
735 bytestream_put_byte (&buf, ctx->alpha_bits >> 3);
736 bytestream_put_byte (&buf, 0); // reserved
737 if (ctx->quant_sel != QUANT_MAT_DEFAULT) {
738 bytestream_put_byte (&buf, 0x03); // matrix flags - both matrices are present
739 bytestream_put_buffer(&buf, ctx->quant_mat, 64); // luma quantisation matrix
740 bytestream_put_buffer(&buf, ctx->quant_chroma_mat, 64); // chroma quantisation matrix
741 } else {
742 bytestream_put_byte (&buf, 0x00); // matrix flags - default matrices are used
743 }
744 bytestream_put_be16 (&tmp, buf - *orig_buf); // write back frame header size
745 return buf;
746}
747
748/* Return the assembled-frame buffer to its pool when the packet is freed. */
749static void prores_vk_packet_free(void *opaque, uint8_t *data)
750{
751 av_refstruct_unref(&opaque);
752}
753
755{
756 ProresVulkanContext *pv = avctx->priv_data;
757 ProresContext *ctx = &pv->ctx;
759 FFVulkanContext *vkctx = &pv->vkctx;
760 FFVulkanFunctions *vk = &vkctx->vkfn;
761 FFVkBuffer *wrap_buf = pd->gathered_ref[0];
762 uint8_t *orig_buf, *buf, *slice_sizes;
763 uint8_t *picture_size_pos;
764 int picture_idx;
765 int frame_size, picture_size;
766 FFVkBuffer *frame_size_buf;
767 VkMappedMemoryRange invalidate_data;
768
769 /* Make sure encoding's done */
770 ff_vk_exec_wait(vkctx, exec);
771
772 /* Invalidate the gathered bitstream if needed */
773 invalidate_data = (VkMappedMemoryRange) {
774 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
775 .offset = 0,
776 .size = VK_WHOLE_SIZE,
777 };
778 if (!(wrap_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
779 invalidate_data.memory = wrap_buf->mem;
780 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
781 }
782
783 /* Write frame atom */
784 orig_buf = wrap_buf->mapped_mem;
785 buf = write_frame_header(avctx, ctx, &orig_buf, pd->flags,
786 pd->color_primaries, pd->color_trc,
787 pd->colorspace);
788
789 for (picture_idx = 0; picture_idx < ctx->pictures_per_frame; picture_idx++) {
790 FFVkBuffer *slice_sizes_buf = pd->slice_sizes_ref[picture_idx];
791 const uint32_t *sizes;
792
793 frame_size_buf = pd->frame_size_ref[picture_idx];
794
795 /* Invalidate slice sizes if needed */
796 if (!(frame_size_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
797 invalidate_data.memory = frame_size_buf->mem;
798 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
799 }
800 if (!(slice_sizes_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
801 invalidate_data.memory = slice_sizes_buf->mem;
802 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
803 }
804
805 /* Write picture header */
806 picture_size_pos = buf + 1;
807 bytestream_put_byte(&buf, 0x40); // picture header size (in bits)
808 buf += 4; // picture data size will be stored here
809 bytestream_put_be16(&buf, ctx->slices_per_picture);
810 bytestream_put_byte(&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
811
812 /* Write the seek table from the per-slice sizes; the payload itself
813 * was already packed to match by the gather pass. */
814 slice_sizes = buf;
815 sizes = (const uint32_t *)slice_sizes_buf->mapped_mem;
816 for (int i = 0; i < ctx->slices_per_picture; i++)
817 bytestream_put_be16(&buf, sizes[i]);
818
819 /* Calculate final size */
820 buf += *(int*)frame_size_buf->mapped_mem;
821
822 if (picture_idx == 0) {
823 av_assert1(((slice_sizes + ctx->slices_per_picture * 2) -
824 wrap_buf->mapped_mem) == pv->payload_off);
825 } else {
826 /* Relocate the second picture's payload from its scratch buffer */
827 FFVkBuffer *scratch = pd->gathered_ref[1];
828 if (!(scratch->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
829 invalidate_data.memory = scratch->mem;
830 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
831 }
832 memcpy(slice_sizes + ctx->slices_per_picture * 2, scratch->mapped_mem,
833 buf - (slice_sizes + ctx->slices_per_picture * 2));
835 }
836
837 /* Write picture size with header */
838 picture_size = buf - (picture_size_pos - 1);
839 bytestream_put_be32(&picture_size_pos, picture_size);
840
841 /* Slice output buffers no longer needed */
842 av_refstruct_unref(&pd->out_data_ref[picture_idx]);
843 av_refstruct_unref(&pd->slice_sizes_ref[picture_idx]);
844 av_refstruct_unref(&pd->slice_data_ref[picture_idx]);
845 av_refstruct_unref(&pd->slice_score_ref[picture_idx]);
846 av_refstruct_unref(&pd->frame_size_ref[picture_idx]);
847 }
848
849 /* Write frame size in header */
850 orig_buf -= 8;
851 frame_size = buf - orig_buf;
852 bytestream_put_be32(&orig_buf, frame_size);
853
854 memset(buf, 0, AV_INPUT_BUFFER_PADDING_SIZE);
855
856 /* Hand the buffer to the packet with no copy: pkt->buf references the
857 * pooled Vulkan buffer, returned to its pool when the packet is freed. */
858 pkt->buf = av_buffer_create(wrap_buf->mapped_mem, wrap_buf->size,
860 if (!pkt->buf) {
862 return AVERROR(ENOMEM);
863 }
864 pd->gathered_ref[0] = NULL; /* ownership passed to pkt->buf */
865 pkt->data = wrap_buf->mapped_mem;
866 pkt->size = frame_size;
867
868 pkt->pts = pd->pts;
869 pkt->dts = pd->pts;
870 pkt->duration = pd->duration;
871 pkt->flags |= AV_PKT_FLAG_KEY * pd->key_frame;
872
873 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
874 pkt->opaque = pd->frame_opaque;
875 pkt->opaque_ref = pd->frame_opaque_ref;
877 }
878
879 av_log(avctx, AV_LOG_VERBOSE, "Encoded data: %iMiB\n", pkt->size / (1024*1024));
880
881 return 0;
882}
883
885{
886 int err;
887 ProresVulkanContext *pv = avctx->priv_data;
888 ProresContext *ctx = &pv->ctx;
890 FFVkExecContext *exec;
891 AVFrame *frame;
892
893 while (1) {
894 /* Roll an execution context */
895 exec = ff_vk_exec_get(&pv->vkctx, &pv->e);
896
897 /* If it had a frame, immediately output it */
898 if (exec->had_submission) {
899 exec->had_submission = 0;
900 pv->in_flight--;
901 return get_packet(avctx, exec, pkt);
902 }
903
904 /* Get next frame to encode */
905 frame = pv->frame;
906 err = ff_encode_get_frame(avctx, frame);
907 if (err < 0 && err != AVERROR_EOF) {
908 return err;
909 } else if (err == AVERROR_EOF) {
910 if (!pv->in_flight)
911 return err;
912 continue;
913 }
914
915 /* Encode frame */
916 pd = exec->opaque;
917 pd->color_primaries = frame->color_primaries;
918 pd->color_trc = frame->color_trc;
919 pd->colorspace = frame->colorspace;
920 pd->pts = frame->pts;
921 pd->duration = frame->duration;
922 pd->flags = frame->flags;
923 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
924 pd->frame_opaque = frame->opaque;
925 pd->frame_opaque_ref = frame->opaque_ref;
926 frame->opaque_ref = NULL;
927 }
928
929 err = vulkan_encode_prores_submit_frame(avctx, exec, frame, 0);
930 if (ctx->pictures_per_frame > 1)
932
933 /* Submit execution context */
934 ff_vk_exec_submit(&pv->vkctx, exec);
936 if (err < 0)
937 return err;
938
939 pv->in_flight++;
940 if (pv->in_flight < pv->async_depth)
941 return AVERROR(EAGAIN);
942 }
943
944 return 0;
945}
946
978
980{
981 ProresVulkanContext *pv = avctx->priv_data;
982 ProresContext *ctx = &pv->ctx;
983 int err = 0, i, q;
984 FFVulkanContext *vkctx = &pv->vkctx;
985
986 /* Init vulkan */
987 RET(ff_vk_init(vkctx, avctx, NULL, avctx->hw_frames_ctx));
988
989 pv->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
990 if (!pv->qf) {
991 av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
992 return AVERROR(ENOTSUP);
993 }
994
995 RET(ff_vk_exec_pool_init(vkctx, pv->qf, &pv->e, 1, 0, 0, 0, NULL));
996
997 /* Init common prores structures */
998 err = ff_prores_kostya_encode_init(avctx, ctx, vkctx->frames->sw_format);
999 if (err < 0)
1000 return err;
1001
1002 /* Temporary frame */
1003 pv->frame = av_frame_alloc();
1004 if (!pv->frame)
1005 return AVERROR(ENOMEM);
1006
1007 /* Async data pool */
1008 pv->async_depth = pv->e.pool_size;
1009 pv->exec_ctx_info = av_calloc(pv->async_depth, sizeof(*pv->exec_ctx_info));
1010 if (!pv->exec_ctx_info)
1011 return AVERROR(ENOMEM);
1012 for (int i = 0; i < pv->async_depth; i++)
1013 pv->e.contexts[i].opaque = &pv->exec_ctx_info[i];
1014
1015 /* Compile shaders used by encoder */
1022
1023 /* Size slots for the entropy coder's worst case; bits_per_mb is only a rate-control average */
1024 {
1025 size_t samples = ctx->mbs_per_slice *
1026 (256 + (ctx->chroma_factor == CFACTOR_Y444 ? 512 : 256));
1027 pv->slice_slot_size = 2 + 2 * ctx->num_planes + samples * 8;
1028 if (ctx->alpha_bits)
1029 pv->slice_slot_size += (ctx->mbs_per_slice * 256 *
1030 (1 + ctx->alpha_bits + 1) + 7) >> 3;
1032 UINT16_MAX + 2 + 2 * ctx->num_planes);
1034 }
1035
1036 /* First picture's payload offset: everything before it in the stream has
1037 * a static size, so the gather pass writes the payload directly in place */
1038 {
1039 uint8_t tmp[256];
1040 uint8_t *start = tmp;
1041 uint8_t *end = write_frame_header(avctx, ctx, &start, 0, 0, 0, 0);
1042 pv->payload_off = (end - tmp) + 8 + ctx->slices_per_picture * 2;
1043 }
1044
1045 if (ctx->alpha_bits)
1047
1048 /* Create prores data tables uniform buffer. */
1050 sizeof(ProresDataTables), NULL, NULL,
1051 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
1052 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
1053 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1054 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
1055 RET(ff_vk_map_buffer(vkctx, &pv->prores_data_tables_buf, (void *)&pv->tables, 0));
1056 for (q = 0; q < MAX_STORED_Q; ++q) {
1057 for (i = 0; i < 64; i++) {
1058 pv->tables->qmat[q][i] = ctx->quants[q][ctx->scantable[i]];
1059 pv->tables->qmat_chroma[q][i] = ctx->quants_chroma[q][ctx->scantable[i]];
1060 }
1061 }
1062 for (q = MAX_STORED_Q; q < 128; ++q) {
1063 for (i = 0; i < 64; i++) {
1064 pv->tables->qmat[q][i] = ctx->quant_mat[ctx->scantable[i]] * q;
1065 pv->tables->qmat_chroma[q][i] = ctx->quant_chroma_mat[ctx->scantable[i]] * q;
1066 }
1067 }
1068
1069fail:
1070 return err;
1071}
1072
1073#define OFFSET(x) offsetof(ProresVulkanContext, x)
1074#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1075
1076static const AVOption options[] = {
1077 { "mbs_per_slice", "macroblocks per slice", OFFSET(ctx.mbs_per_slice),
1078 AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE },
1079 { "profile", NULL, OFFSET(ctx.profile), AV_OPT_TYPE_INT,
1080 { .i64 = PRORES_PROFILE_AUTO },
1081 PRORES_PROFILE_AUTO, PRORES_PROFILE_4444XQ, VE, .unit = "profile" },
1082 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_AUTO },
1083 0, 0, VE, .unit = "profile" },
1084 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY },
1085 0, 0, VE, .unit = "profile" },
1086 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT },
1087 0, 0, VE, .unit = "profile" },
1088 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_STANDARD },
1089 0, 0, VE, .unit = "profile" },
1090 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_HQ },
1091 0, 0, VE, .unit = "profile" },
1092 { "4444", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444 },
1093 0, 0, VE, .unit = "profile" },
1094 { "4444xq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444XQ },
1095 0, 0, VE, .unit = "profile" },
1096 { "vendor", "vendor ID", OFFSET(ctx.vendor),
1097 AV_OPT_TYPE_STRING, { .str = "Lavc" }, 0, 0, VE },
1098 { "bits_per_mb", "desired bits per macroblock", OFFSET(ctx.bits_per_mb),
1099 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE },
1100 { "quant_mat", "quantiser matrix", OFFSET(ctx.quant_sel), AV_OPT_TYPE_INT,
1101 { .i64 = -1 }, -1, QUANT_MAT_DEFAULT, VE, .unit = "quant_mat" },
1102 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 },
1103 0, 0, VE, .unit = "quant_mat" },
1104 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_PROXY },
1105 0, 0, VE, .unit = "quant_mat" },
1106 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_LT },
1107 0, 0, VE, .unit = "quant_mat" },
1108 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_STANDARD },
1109 0, 0, VE, .unit = "quant_mat" },
1110 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_HQ },
1111 0, 0, VE, .unit = "quant_mat" },
1112 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_DEFAULT },
1113 0, 0, VE, .unit = "quant_mat" },
1114 { "alpha_bits", "bits for alpha plane", OFFSET(ctx.alpha_bits), AV_OPT_TYPE_INT,
1115 { .i64 = 16 }, 0, 16, VE },
1116 { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT,
1117 { .i64 = 1 }, 1, INT_MAX, VE },
1118 { NULL }
1119};
1120
1121static const AVClass proresenc_class = {
1122 .class_name = "ProRes vulkan encoder",
1123 .item_name = av_default_item_name,
1124 .option = options,
1125 .version = LIBAVUTIL_VERSION_INT,
1126};
1127
1129 HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
1131 NULL,
1132};
1133
1135 .p.name = "prores_ks_vulkan",
1136 CODEC_LONG_NAME("Apple ProRes (iCodec Pro)"),
1137 .p.type = AVMEDIA_TYPE_VIDEO,
1138 .p.id = AV_CODEC_ID_PRORES,
1139 .priv_data_size = sizeof(ProresVulkanContext),
1140 .init = encode_init,
1143 .p.capabilities = AV_CODEC_CAP_DELAY |
1148 .hw_configs = prores_ks_hw_configs,
1149 .color_ranges = AVCOL_RANGE_MPEG,
1150 .p.priv_class = &proresenc_class,
1153};
const FFCodec ff_prores_ks_vulkan_encoder
#define VE
Definition amfenc_av1.c:30
const unsigned char ff_seg_gather_comp_spv_data[]
const unsigned int ff_seg_gather_comp_spv_len
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
Libavcodec external API header.
refcounted data buffer API
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition bytestream.h:372
#define flags(name, subs,...)
Definition cbs_h264.c:74
#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 const AVColorPrimariesDesc color_primaries[AVCOL_PRI_NB]
Definition csp.c:76
static av_cold int encode_close(AVCodecContext *avctx)
Definition dcaenc.c:354
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 FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition encode.h:34
#define MAX_PLANES
Definition ffv1.h:44
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
static const uint8_t frame_size[4]
Definition g723_1.h:222
#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
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#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_FLAG_INTERLACED_DCT
Use interlaced DCT.
Definition avcodec.h:310
#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_PRORES
Definition codec_id.h:198
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
#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_DEVICE(format, device_type_)
Definition hwconfig.h:97
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
static const int sizes[][2]
Definition img2dec.c:62
#define av_log2
Definition intmath.h:84
#define DCTSIZE
Definition jfdctfst.c:73
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
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:2542
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:2070
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:2373
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:310
int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Definition vulkan.c:1016
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:357
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:590
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1443
int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Sets an image descriptor for specified shader and binding.
Definition vulkan.c:2517
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2638
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:2651
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition vulkan.c:1230
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:2027
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:599
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:1958
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2614
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2407
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:571
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:881
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2591
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:2555
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:297
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:687
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:1256
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:2267
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:777
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:2581
const char * desc
Definition libsvtav1.c:83
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
const char data[16]
Definition mxf.c:149
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
const AVProfile ff_prores_profiles[]
Definition profiles.c:175
#define FRAME_ID
Definition proresdata.h:28
static const AVClass proresenc_class
av_cold int ff_prores_kostya_encode_init(AVCodecContext *avctx, ProresContext *ctx, enum AVPixelFormat pix_fmt)
@ QUANT_MAT_STANDARD
@ QUANT_MAT_DEFAULT
#define CFACTOR_Y444
#define CFACTOR_Y422
@ PRORES_PROFILE_4444
@ PRORES_PROFILE_STANDARD
@ PRORES_PROFILE_LT
@ PRORES_PROFILE_4444XQ
@ PRORES_PROFILE_AUTO
@ PRORES_PROFILE_HQ
@ PRORES_PROFILE_PROXY
#define MAX_MBS_PER_SLICE
#define MAX_STORED_Q
const unsigned int ff_prores_ks_alpha_data_comp_spv_len
const unsigned char ff_prores_ks_alpha_data_comp_spv_data[]
static int init_estimate_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned int ff_prores_ks_slice_data_comp_spv_len
const unsigned int ff_prores_ks_encode_slice_comp_spv_len
static int init_gather_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static av_cold int encode_init(AVCodecContext *avctx)
static av_cold int encode_close(AVCodecContext *avctx)
const unsigned int ff_prores_ks_trellis_node_comp_spv_len
static int init_alpha_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static const AVCodecHWConfigInternal *const prores_ks_hw_configs[]
static int vulkan_encode_prores_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static int init_trellis_node_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static void prores_vk_packet_free(void *opaque, uint8_t *data)
static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
#define OFFSET(x)
static int vulkan_encode_prores_submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame, int picture_idx)
const unsigned char ff_prores_ks_trellis_node_comp_spv_data[]
static uint8_t * write_frame_header(AVCodecContext *avctx, ProresContext *ctx, uint8_t **orig_buf, int flags, enum AVColorPrimaries color_primaries, enum AVColorTransferCharacteristic color_trc, enum AVColorSpace colorspace)
const unsigned int ff_prores_ks_estimate_slice_comp_spv_len
static int init_encode_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[]
const unsigned char ff_prores_ks_slice_data_comp_spv_data[]
const unsigned char ff_prores_ks_encode_slice_comp_spv_data[]
bitstream writer API
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
A reference to a data buffer.
Definition buffer.h:82
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
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.
VkDeviceAddress slice_sizes
VkDeviceAddress bytestream
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:150
int had_submission
Definition vulkan.h:131
VkCommandBuffer buf
Definition vulkan.h:139
FFVkExecContext * contexts
Definition vulkan.h:269
int pool_size
Definition vulkan.h:274
AVHWFramesContext * frames
Definition vulkan.h:333
AVVulkanDeviceContext * hwctx
Definition vulkan.h:329
VkMemoryPropertyFlagBits host_cached_flag
Definition vulkan.h:325
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
Definition vulkan.h:302
FFVulkanFunctions vkfn
Definition vulkan.h:294
unsigned mb_height
height of the current picture in mb
Definition proresdec.h:54
const struct prores_profile * profile_info
unsigned mb_width
width of the current picture in mb
Definition proresdec.h:53
int16_t qmat_chroma[128][64]
AVRefStructPool * frame_size_buf_pool
AVRefStructPool * slice_data_buf_pool
AVRefStructPool * gathered_buf_pool
AVRefStructPool * slice_sizes_buf_pool
AVVulkanDeviceQueueFamily * qf
VulkanEncodeProresFrameData * exec_ctx_info
FFVulkanShader slice_data_shd[2]
AVRefStructPool * slice_score_buf_pool
VkDeviceAddress sparse
VkDeviceAddress compacted
int16_t rows[MAX_PLANES *MAX_MBS_PER_SLICE *256]
int error[MAX_STORED_Q][4]
int total_bits[MAX_STORED_Q]
int total_error[MAX_STORED_Q]
int bits[MAX_STORED_Q][4]
enum AVColorTransferCharacteristic color_trc
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
static AVFormatContext * ctx
Definition movenc.c:49
#define NONE
Definition vf_drawvg.c:262
@ FF_VK_REP_INT
Definition vulkan.h:433
#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
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition vulkan.h:614